Hibernate对象从数据库重新加载

时间:2013-11-07 18:08:42

标签: java mysql spring hibernate dbunit

我有一个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());

我也尝试过刷新(account1)和session.clear(),但它们没有用。

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

谢谢, 迭。

2 个答案:

答案 0 :(得分:0)

我认为您看到了这种行为,因为您的事务是在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

答案 1 :(得分:-1)

我不知道hibernate,但这是使用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);
}