Java Hibernate refresh()或getSingleResult()返回缓存实体(?)

Java Hibernate refresh()或getSingleResult()返回缓存实体(?),java,hibernate,jpa,caching,wildfly,Java,Hibernate,Jpa,Caching,Wildfly,我在Wildfly(JBoss)10上使用Hibernate2.1从数据库中获取实体。以下是实体的模型: @Entity @Table(name = "account") @NamedQuery(name = "Account.findAll", query = "SELECT a FROM Account a") public class Account implements Serializable { private

我在Wildfly(JBoss)10上使用Hibernate2.1从数据库中获取实体。以下是实体的模型:

@Entity
@Table(name = "account")
@NamedQuery(name = "Account.findAll", query = "SELECT a FROM Account a")
public class Account implements Serializable {

     private int id;
     private double balance;
     private double bonus;

     @Id
     public int getId() {
        return this.id;
     }
     // Rest of the fields/setters/getters ommited
}
我实现了一个RESTAPI调用,它更新给定帐户的余额。帐户首先从数据库中检索、验证,然后通过MySQL中单独的bean管理事务更新余额。完成此操作后,我被要求对该帐户执行其他操作,我需要更新(新)余额。查找以下所附代码:

@Stateless
@Path("/financial")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class FinancialApi {
   
   @Inject private AccountBean accountBean;
   @Inject private AccountBalanceBean accountBalanceBean;

   @POST
   @Path("/balance/add")
   public Response addBalance(TransactionProperties properties) {
      Account account;
      try {
         account = accountBean.get(properties.getAccountId());
         validateAccount(account);
      } catch (ValidationException ex) {
          return Response.status(Response.Status.BAD_REQUEST).build();
      }
      // Update balance
      accountBalanceBean.updateBalance(account.getId(), properties.getAmount());
      // Refresh from DB to retrieve updated balance
      accountBean.refresh(account);
      // Do stuff with refreshed account data here
      return Response.ok().build();
   }
}
处理帐户的“DAO”EJB

@Stateless
@LocalBean
public class AccountEJBean {
   
    @PersistenceContext(unitName = "my-unit-name")
    private EntityManager em;

    public Account get(int id) {
        try {
           return (Account) em.createQuery("SELECT a FROM Account a WHERE a.id = :id")
                        .setParameter("id", id)
                        .setMaxResults(1)
                        .getSingleResult();
        } catch (NoResultException ex) {
            return null;
        }
    }

    public void refresh(Account account) {
         em.refresh(account);
    }

}
以及使用bean管理的事务来更新帐户余额的EJB(严重减少)示例:

@Stateless
@LocalBean
@TransactionManagement(TransactionManagementType.BEAN)
public class AccountBalanceEJBean {

        @PersistenceContext(unitName = "my-unit-name")
        private EntityManager em;
        @Resource
        private UserTransaction transaction;
         
        public boolean updateBalance(int id, float price) {
            try {
                transaction.begin();
                getUpdateQuery(id, price).executeUpdate();
                transaction.commit();
            } catch (Exception ex) { 
                transaction.rolloback();
            }
        }
}
这是我的persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence">
  <persistence-unit name="my-unit-name" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>java:/jboss/datasources/SQLDatasource</jta-data-source>
    <class>mypackage.Account</class>
    <properties>
      <property name="hibernate.generate_statistics" value="false"/>
      <property name="hibernate.connection.useUnicode" value="true"/>
      <property name="hibernate.connection.characterEncoding" value="UTF-8"/>
    </properties>
    </persistence-unit>
</persistence>

org.hibernate.ejb.HibernatePersistence
java:/jboss/datasources/SQLDatasource
我的包裹
在我尝试从数据库中刷新帐户数据之前,这一切都很好。此时,我尝试过的每个案例都会刷新帐户,没有任何问题,但帐户的数据不会得到更新。我仍在检索帐户最初检索时的“过时”数据。环顾四周一段时间后,我想这可能与Hibernate缓存机制有关。我尝试了以下方法:

  • get()
    方法上的实体与EntityManager分离,并将
    refresh()
    替换为
    get()
  • 调用
    em.clear()
    ,然后再次使用
    get()
    调用检索实体
  • 正在尝试使用em.getEntityManagerFactory().get().RejectAll()清除缓存。
  • 设置提示“javax.persistence.cache.retrieveMode”和“javax.persistence.cache.storeMode”以绕过
    get()
    方法的查询
  • 这些似乎都不起作用。我尝试在代码中更新实体并设置随机值,每次实体在初始检索状态下刷新时(不是数据库中的实体,即使我更改了不同于此处未提及的balance的字段)

    据我所知,二级缓存在Hibernate上默认是禁用的,据我所知,这里的情况并非如此。考虑到这一点,我转到了一级缓存,但我似乎不知道如何从实体管理器检索会话(或者如果这里存在会话),以便清除导致问题的缓存。作为旁注,我不确定有一个不会被
    refresh()
    方法覆盖的一级缓存有什么意义,以及它在分布式环境中是如何工作的

    如果这有帮助,则注入的EntityManager实例是类
    org.jboss.as.jpa.container.TransactionScopedEntityManager
    的实例

    有什么想法吗

    更新:我在第二个bean中复制了
    get()
    代码,我们称之为AccountBean2,它也被注入到API类中。它现在似乎起作用了。我很有信心这是一个缓存问题,但我仍然不知道如何纠正最初的问题,所以问题仍然存在