1.简介
Spring为程序性和声明性事务提供支持。
1.1程序化交易
对于程序性事务,需要显式编写事务管理代码,以便在一切成功后提交,并在出现问题时回滚。 在这种情况下,事务管理代码与业务逻辑紧密绑定。
1.2声明式交易
声明式事务将事务管理代码与业务逻辑分开。 Spring通过Spring上下文中的XML配置或@Transactional注释,使用事务建议(使用AOP)来支持声明式事务。
在本教程中,我们将特别关注@Transactional批注及其工作方式。
2.实施
要在基于Spring的应用程序中开始使用@Transactional批注,我们需要先在Spring应用程序中启用批注,方法是将所需的配置添加到spring上下文文件中–
<tx:annotation-driven transaction-manager="txManager"/>
接下来是定义事务管理器Bean,其名称与上述transaction-manager属性值中指定的名称相同。
交易经理可能是–
2.1数据源交易管理器
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref= "datasource" />
</bean>
2.2休眠事务管理器
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref= "sessionFactory" />
</bean>
2.3 JPA交易管理器
<bean id="txManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
现在,我们准备在类或方法级别使用@Transactional批注。
@Transactional(value = "myTransactionManager", propagation = Propagation.REQUIRED, readOnly = true)
public void myMethod() {
...
}
3.相关链接
4.了解@Transactional批注
在较高的层次上,当一个类在其本身或其成员上声明@Transactional时,Spring将创建一个代理,该代理实现与您要注释的类相同的接口。 换句话说,Spring将Bean包装在代理中,而Bean本身对此一无所知。 代理为Spring提供了一种在方法调用之前,之后或周围将行为注入到被代理对象中的方式。
在内部,它与使用事务通知(使用AOP)相同,在代理中首先创建代理,然后在目标bean的方法之前/之后调用代理。
生成的代理对象提供了由Spring创建的TransactionInterceptor 。 因此,当从客户端代码调用@Transactional方法时,首先从代理对象调用TransactionInterceptor ,该代理对象开始事务并最终在目标bean上调用该方法。 调用完成后, TransactionInterceptor相应地提交/回滚事务。
注意,只有来自目标bean“外部”的调用才通过代理。
5.了解传播和只读注释属性
5.1交易只读
如果未将readOnly属性显式设置为true ,则将具有读/写事务。
显式地指定readOnly属性总是更好的选择,因为我们已经注意到,Hibernate大大改善了性能。
5.2交易传播
默认情况下,事务传播是必需的,这意味着同一事务将从事务调用方传播到事务被调用方。 它将创建一个新事务,或在可用的情况下重用该事务。 例如,如果只读事务调用读写事务方法,则整个事务将为只读。
根据事务传播属性(例如REQUIRES_NEW ),有时会在某个时候挂起/暂停现有事务,总是启动并最终提交新事务,然后恢复第一个事务。
5.3隔离度
隔离级别定义了事务之间的合同。
- 读取未提交 –线程尚未提交事务且另一个线程正在读取脏数据时,允许进行脏读。
- 已提交读 –不允许脏读。 仅允许线程读取另一个线程中其他正在运行的事务已提交的值。
- 重复读取 –如果在同一事务中两次读取相同的数据,则它将始终相同。 此级别保证一旦读取就不会更改任何数据。
- 可序列化 –事务在所有级别都处于锁定状态(读取,范围和写入锁定),因此,它们以固定的顺序执行。 它不允许并发事务并导致性能下降。
使用“可重复读取”隔离级别,从事务开始就维护数据库的状态。 如果您检索会话1的值,则在会话2更新值,在会话1再次检索它会返回相同的结果。
6.源代码下载
翻译自: https://www.javacodegeeks.com/2016/05/understanding-transactional-annotation-spring.html