如何在Spring Data中使用@Transactional?


82

我刚刚开始从事Spring数据,Hibernate,MySQL,JPA项目。我切换到spring-data,以便不必担心手动创建查询。

我注意到@Transactional当您使用spring-data时不需要使用of,因为我也尝试了没有注释的查询。

有特定的原因为什么我应该/不应该使用@Transactional注释?

作品:

@Transactional
public List listStudentsBySchool(long id) {
    return repository.findByClasses_School_Id(id);
}

也可以:

public List listStudentsBySchool(long id) {
    return repository.findByClasses_School_Id(id);
}

提前致谢!

Answers:


140

您实际上在问什么?@Repository注释或的用法@Transactional

@Repository根本不需要,因为您声明的接口将由Spring Data基础结构创建并激活异常转换的代理支持。因此,在Spring Data仓库接口上使用此批注根本没有任何作用。

@Transactional-对于JPA模块,我们在支持代理(SimpleJpaRepository)的实现类上具有此批注。这有两个原因:首先,持久化和删除对象需要JPA中的事务。因此,我们需要确保事务正在运行,方法是使用注释方法@Transactional

findAll()findOne(…)这样使用的读取方法@Transactional(readOnly = true)不是严格必需的,但是会触发事务基础结构中的一些优化(将设置为FlushModeMANUAL以使持久性提供程序在关闭时可能会跳过脏检查EntityManager)。除此之外,该标志还在JDBC连接上设置,这会导致对该级别的进一步优化。

根据您使用的数据库的不同,它可能会忽略表锁,甚至拒绝您可能意外触发的写操作。因此,我们建议也使用@Transactional(readOnly = true)for查询方法,您可以轻松地实现将该注释添加到存储库接口。确保@Transactional在该接口中可能已声明或重新装饰的操作方法上添加一个普通格式。


8
简而言之:我应该在所有DAO方法的添加/编辑/删除查询上使用@Transactional,在选择查询上使用@Transaction(readOnly = true)?
拜伦·沃巴赫

20
究竟。最简单的方法是@Transactional(readOnly = true)在接口上使用(因为它通常包含大部分finder方法),并使用plain覆盖每个修改查询方法的此设置@Transactional。这实际上就是在中完成的方式SimpleJpaRepositoy
奥利弗·德罗博姆

@Oliver感谢您的全面解释。.但是通过其他链接[transaction-pit-falls] < ibm.com/developerworks/java/library/j-ts1/index.html#listing8 >。它说:最重要的是,当您使用基于ORM的框架时,只读标志是非常无用的,并且在大多数情况下会被忽略。但是,如果您仍然坚持使用它,则始终将传播模式设置为SUPPORTS。阅读此内容后,我不确定是否应该单独使用(readOnly = true)..是否应始终将其与传播模式一起用作支持。
Anupam Gupta

8
在本文的这一部分中,几乎所有内容都是错误的。通过指示您没有编写,JDBC驱动可以(将)提高数据库交互的性能。它还可以检测并拒绝意外发出的写入。最重要的是,Spring会在只读模式下禁用JPA /休眠刷新,如果您读取大型对象图,因为提供程序不需要对它进行脏检查,则Spring会极大地影响性能。该标志可能不会对交易本身产生重大影响,但是到目前为止,并不是所有要考虑的因素。
奥利弗·德罗博姆

对于大型对象图或加载大量托管对象的用例,我可以保证性能的提高。
Shailendra 2015年

3

我认为这个问题有点广泛,不能在数据访问层的注释中减少。我们需要考虑应用程序的整个堆栈,我们要应用的交易策略等等。在IBM developerWorks网站上,Mark Richards撰写了有关该主题的非常全面的文章集。您可以在这里找到第一个:https : //developer.ibm.com/articles/j-ts1/

最好的祝福


2

您应该使用@Repository注释

这是因为@Repository用于将未经检查的SQL异常转换为Spring Excpetion,并且您应该处理的唯一异常是DataAccessException


10
通常在使用Spring时是这样,但是由于Spring数据存储库已经由Spring代理支持-使用@Repository没有任何区别。
亚历山大·布隆斯科尔德

0

我们还使用@Transactional批注来锁定记录,以便另一个线程/请求不会更改读取。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.