我在显示数据库中的数据时遇到了一个问题。如果我更新一个对象,有时会得到旧数据,有时会得到新数据。Update函数工作正常(我可以在DB中看到正确的更新),而read函数似乎得到了缓存的数据。我已经尝试禁用这两个缓存,并尝试在更新/保存期间打开和关闭session
,但它仍然不起作用。
User和Store bean都有Lazy fetch。
读取功能:
public static List<Store> getStoreByUser(User user)
throws HibernateException {
List<Store> result = null;
Session session = sessionFactory.getCurrentSession();
Transaction transaction = null;
try {
transaction = session.getTransaction();
Criteria criteria = session.createCriteria(Store.class);
criteria.add(Restrictions.eq("userUserID", user));
result = criteria.list();
} catch (HibernateException he) {
logger.error("No Store found for user: = " + user, he);
throw he;
}
return result;
}
更新/保存功能:
public static Integer insertOrUpdateStore(Store store)
throws HibernateException {
Integer id = null;
Session session = sessionFactory.getCurrentSession();
Transaction transaction = null;
try {
transaction = session.getTransaction();
if (store.getStoreID() != null && store.getStoreID() != 0) {
session.merge(store);
transaction.commit();
} else {
id = (Integer) session.save(store);
transaction.commit();
}
} catch (HibernateException he) {
if (transaction != null) {
transaction.rollback();
}
} finally {
}
return id;
}
4条答案
按热度按时间jm81lzqq1#
我有同样的问题,我的查询select * 返回旧数据。
我将尝试在transaction.commit()之前/之后添加session.flush()或session.clear(),但它没有给出积极的结果
iovurdzv2#
通常,你有一个isolation level“read committed”。这让你的事务可以看到其他事务提交的更改。隔离级别是由底层dbms实现的,而不是hibernate。
你不能禁用第一级缓存(可能是通过使用无状态会话,它不应该用于一般目的)。当执行查询时,NH总是从该高速缓存中返回值,当它在那里被发现时,以确保你不会在内存中多次获得相同的db记录。
如果这对你来说是一个问题,你应该切换到更高的隔离级别。例如,可重复读取(这意味着它说:当多次阅读相同的数据时,您总是得到相同的结果)。仍然有机会看到其他事务的更改。使用隔离级别序列化,您应该不会再有这种问题。
注意:切换到另一个隔离级别对大多数系统来说是一个突破性的更改,应该仔细计划。
7rtdyuoh3#
你可以打开一个新的session,以便从session缓存中获取“新鲜”(从数据库更新)的数据,而不需要旧的实体。在下面的例子中,你可以看到一个实体正在从数据库中查询。你也可以使用相同的机制返回实体而不是布尔值,或者调用
session.Refresh()
(当然是从你当前的session)来刷新数据库中的最新更改:我希望这对你有帮助。
xghobddn4#
您可以驱逐旧数据,以确保从db而不是从L1和L2缓存中获取数据。
此外,您还必须确保您没有处于
REPEATABLE_READ
隔离级别。在这种隔离模式下,它保证同一事务中的两次读取将始终返回相同的结果。由于隔离级别优先于缓存回收,该高速缓存回收不会有任何可见的效果。有一种方法可以解决此问题:将事务隔离级别声明为
READ_UNCOMMITTED
或READ_COMMITTED
。