【问题标题】:Hibernate object re-loading from database从数据库重新加载休眠对象
【发布时间】:2013-11-07 18:08:41
【问题描述】:

我有一个 Spring + Hibernate + DBUnit + MySQL 应用程序。

步骤如下:

1. I launch the application.
2. A DBUnit test loads data directly into the database (via JDBC).
3. I perform operations and HQL queries to assert the results.


在第 2 步之后,我立即从控制台查询数据库并确认数据已正确加载。我的问题是,在第 3 步中,我通过 HQL 查询获得的对象不包含在第 2 步中加载的值,而是包含原始值(第 1 步及之前存在的值)。

在阅读了这里的一些帖子后,我决定在第 3 步之前清理会话缓存和二级缓存,以强制 Hibernate 直接获取数据库。但问题依然存在。

是不是我做错了什么?


这是我在第 3 步中尝试的脚本:

在应用程序启动之前(第 1 步),数据库中的帐户余额为 125。在第 2 步中,DBUnit 确实将数据库中的余额更改为 10。

   // A break-point here allows me to check through a console that balance at database is cartainly 10.

   // I query the account and print the balance, which is 125.
   List l1 = this.getHibernateTemplate().find("select a from Account a where a.number = ?", parameter);
   Account account1 = (Account) l1.get(0);
   System.out.println("A.- Account 1 balance: " + account1.getBalance());

   // I clear session cache and second-level cache.
   this.getSession().evict(account1);
   this.getSessionFactory().evict(Account.class);       
   this.getSessionFactory().evictQueries();     

   // I repeat the same query, now expecting to force a database fetch. But it still prints 125 and not 10.
   List l2 = this.getHibernateTemplate().find("select a from Account a where a.number = ?", parameter);
   Account account2 = (Account) l2.get(0);
   System.out.println("B.- Account 2 balance: " + account2.getBalance());

我也尝试过 refresh(account1) 和 session.clear(),但没有成功。

如果这不是正确的解决方案,我愿意听取其他人的意见。

谢谢, 迭戈。

【问题讨论】:

  • 这里的账户余额应该什么时候改变?如果您期望不同的结果,您应该使用新的事务/会话
  • 这个脚本包含在 Spring 为每个服务提供的事务上下文中。加载数据后,dbunit 调用此服务,打开一个新的事务上下文。
  • 杰西,你是对的。你说的我试过了,效果很好。谢谢!

标签: java mysql spring hibernate dbunit


【解决方案1】:

我认为您看到这种行为是因为您的事务是在 REPEATABLE_READ 中配置的。这意味着 Hibernate 保证同一事务中的两次读取将始终返回相同的结果。由于隔离级别优先于您的缓存逐出,因此缓存逐出没有任何可见的效果。

有一种方法可以解决此问题:
将您的事务隔离级别声明为 READ_UNCOMMITTED 或 READ_COMMITTED。如果您使用标准方言,您可能会遇到著名的“标准 JPA 不支持自定义隔离级别”异常。在这种情况下,您可以应用以下解决方法:
春天 3.3:http://amitstechblog.wordpress.com/2011/05/31/supporting-custom-isolation-levels-with-jpa/
春天 3.2:http://shahzad-mughal.blogspot.com/2012/04/spring-jpa-hibernate-support-for-custom.html

【讨论】:

    【解决方案2】:

    我不知道休眠,但这是应该使用 JPA 完成的:

    public <T> T load(Class<T> entityClass, Object pk)
    {
        Map<String, Object> props = new HashMap<>();
        props.put("javax.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);
    
        return getEntityManager().find(entityClass, pk, props);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-23
      • 2017-05-26
      • 1970-01-01
      相关资源
      最近更新 更多