Spring JPA Transaction

时间:2013-04-17 20:19:26

标签: spring hibernate jpa transactions

我在Spring托管交易中遇到了一些奇怪的行为。这是一个Spring MVC应用程序。我将实体直接绑定到Web层。我使用以下服务层代码从数据库加载持久化实体以进行编辑,该代码是从使用@ModelAttribute注释的方法调用的。

@Transactional(readOnly = true)
@PreAuthorize("#id == authentication.principal.id or hasRole('ROLE_ADMIN')")
public User findById(Long id) {
    return repository.findOne(id);
}

提交表单时,数据绑定到此分离实体。作为验证的一部分,我查询数据库以验证为用户指定的电子邮件地址是唯一的。

@Transactional(readOnly = true)
public boolean isEmailAddressUnique(String emailAddress, Long userId){
    return repository.checkEmailAddressUnique(emailAddress, userId) == 0;
}

此时,在执行此查询之前,Hibernate会尝试刷新以前加载的我不理解的分离实体。显然,如果电子邮件地址不是唯一的,则会导致异常。

我正在使用OpenEntityManagerinViewFilter但是我希望这应该将FlushMode设置为NEVER,也许不是。

如果我从isEmailAddressUnique()中删除@Transactional属性,则不会发生刷新,并且按预期工作,我想解决了这个问题,但是我想了解这里发生了什么。

有什么建议吗?

=============

好的,我进一步调查了。所以我使用默认值配置了OpenEntityManagerInViewFilter:

情景一。

[1] MVC Controller在readOnly事务T1中加载User实体 [2]实体被修改为MVC字段绑定的结果 [3]第二个事务在readOnly事务T2中针对Users表运行。 [4] Hibernate刷新T1中加载的实体。 [5] Hibernate发出查询

情景2。

将OEMIVFilter子类化为将FlushMode设置为提交(默认为auto)。

如上所述,步骤[4]和[5]相反,即。即使T2被标记为readOnly,Hibernate仍然会在事务结束时尝试Flush。我可以理解方案1,因为readOnly可能只引用当前事务T2(并且将在执行T2之前尝试同步数据库)。但是我希望在方案2中不应该发布Flush。

1 个答案:

答案 0 :(得分:2)

我在开始时遇到了同样的问题。我们还使用OSIV过滤器,在我们的例子中的问题是事务注释上的readonly标志没有传播到休眠。我们必须确保我们使用properre transactionmanager,更重要的是hibernatevendoradapter。 检查你的配置,如果在持久性和弹簧集成配置后无法解决问题。