Java Hibernate事务问题

Java Hibernate事务问题,java,hibernate,spring,Java,Hibernate,Spring,我们正在使用Hibernate Spring MVC和OpenSessionInView过滤器。 我们遇到了一个问题(伪代码) 我们的问题是,如果验证失败 foo在hibernate会话中被标记为“dirty”(因为我们使用OpenSessionInView,在整个http请求中只有一个会话),当我们加载表单支持对象(如使用HQL查询的一些实体的列表)时,hibernate在执行查询前检查会话中是否有dirty对象,它会看到foo是并刷新它,提交事务2时,更新将写入数据库。 问题是,即使它是一个

我们正在使用Hibernate Spring MVC和OpenSessionInView过滤器。 我们遇到了一个问题(伪代码)

我们的问题是,如果验证失败 foo在hibernate会话中被标记为“dirty”(因为我们使用OpenSessionInView,在整个http请求中只有一个会话),当我们加载表单支持对象(如使用HQL查询的一些实体的列表)时,hibernate在执行查询前检查会话中是否有dirty对象,它会看到foo是并刷新它,提交事务2时,更新将写入数据库。 问题是,即使它是一个只读事务,并且即使在事务2中没有更新foo,hibernate也不知道哪个对象在哪个事务中更新,也不从该事务中只刷新对象。 有什么建议吗?以前有人遇到过类似的问题吗


更新:这篇文章进一步说明了这个问题:

您可以运行get-on-foo将其放入hibernate会话,然后用您在别处创建的对象替换它。但要使其工作,您必须知道对象的所有ID,以便这些ID在休眠时看起来正确。

这里有几个选项。首先,您实际上不需要事务2,因为会话是打开的,您可以从db加载备份对象,从而避免会话上的脏检查。另一个选项是在检索到foo后将其从会话中逐出,然后在需要存储更改时使用session.merge()重新附加它

使用hibernate时,了解封面下到底发生了什么很重要。在每个提交边界,它将尝试刷新当前会话中对对象的所有更改,而不管更改是在当前事务中还是在任何事务中进行的。这就是实际上不需要为会话中已存在的任何对象调用session.update()的方法


希望这有帮助

使用Session.clear()和/或Session.execute()如何?

在过滤器上设置singleSession=false如何?这可能会将您的操作放入单独的会话中,这样您就不必处理一级缓存问题。否则,您可能需要按照上述用户的建议手动分离/附着对象。如果不希望自动刷新内容,也可以在会话中更改刷新模式(FlushMode.MANUAL)。

此处存在设计问题。您认为ORM是数据存储的透明抽象,还是一组数据操作库?我想说Hibernate是前者。它存在的全部原因是为了消除内存中对象状态和数据库状态之间的区别。它确实提供了低级机制,允许您将两者分开并分别处理,但这样做会降低Hibernate的很多价值

所以非常简单-Hibernate=您的数据库。如果您不想持久化某些内容,请不要更改持久化对象


在更新域对象之前验证数据。当然也要验证域对象,但这是最后一道防线。如果在持久对象上确实出现验证错误,请不要接受异常。除非您阻止它,否则Hibernate将做正确的事情,即关闭那里的会话。

实现一个服务层,查看spring的@Transactional注释,并在适用的地方将您的方法标记为@Transactional(readOnly=true)

您的刷新模式可能设置为自动,这意味着您无法真正控制何时发生DB提交


您还可以将刷新模式设置为手动,并且您的服务/repo只会在您告诉他们时尝试将db与您的应用程序同步。

foo正在会话中,替换它是什么意思?调用get(foo.id)然后合并(foo)
transaction 1 
load object foo
transaction 1 end

update foo's properties (not calling session.save or session.update but only foo's setters)

validate foo (using hibernate validator)
if validation fails ?
 go back to edit screen
 transaction 2 (read only)
 load form backing objects from db
 transaction 2 end
 go to view
else 
transaction 3 
session.update(foo)
transaction 3 end