spring整合事物的三种配置
在配置声明事事物前,首先创建一个maven jar项目,一下是目录结构(1-0):
pom.xml 如下(1-1):
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.6.RELEASE</version><!--4.3.14.RELEASE-->
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.12.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.6.RELEASE</version><!--4.3.14.RELEASE-->
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
</dependencies>
以下是主要代码块service的实现用于转账
@Service
//@Transactional(readOnly = true)
public class PayServiceImpl implements PayService {
@Autowired
private SessionFactory sessionFactory;
@Override
public void transferAccounts() {
Session session = sessionFactory.getCurrentSession();
// System.out.println("session:"+session);
AccountEntity accountEntity = session.get(AccountEntity.class, 1L);
AccountEntity accountEntity1 = session.get(AccountEntity.class, 2L);
accountEntity.setAccountMoney(accountEntity.getAccountMoney().subtract(new BigDecimal(200)));
accountEntity1.setAccountMoney(accountEntity1.getAccountMoney().add(new BigDecimal(200)));
try {
session.update(accountEntity);
session.update(accountEntity1);
// throw new RuntimeException();
}catch (Exception e){
throw new PayBusinessException("转账失败...");
}
}
}
声明事事物 applicationContext.xml 配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--引入配置文件属性-->
<!--<context:property-placeholder location="classpath:datasource.properties" />-->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:datasource.properties" />
</bean>
<!--配置数据源-->
<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="${jdbc.driver_class}"/>
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!--整合hibernate中sessionFactory 交给spring 容器管理-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" >
<property name="dataSource" ref="myDataSource" />
<property name="packagesToScan" value="com.aop.transaction.pay" />
<!--配置hibernate额外属性-->
<property name="hibernateProperties">
<props>
<!--设置hibernate方言-->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL57Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!--配置事物管理-->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!--配置声明性事务管理(事务应用一般放在业务层)-->
<!--事物传播性和隔离性-->
<!-- 事务传播行为类型 说明 PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。 PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。 PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类
似的操作。 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="transfer*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="insert*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="add*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="edit*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="delete*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="load*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="find*" propagation="REQUIRED" isolation="DEFAULT"/>
<tx:method name="*" propagation="SUPPORTS" read-only="true" rollback-for="com.aop.transaction.common.base.BaseException" isolation="DEFAULT"/>
</tx:attributes>
</tx:advice>
<!--配置切入点-->
<aop:config>
<aop:pointcut id="pcut" expression="execution( * com.aop.transaction.pay.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="pcut" />
</aop:config>
<!--配置包扫描-->
<context:component-scan base-package="com.aop.transaction.pay" />
</beans>
aop 拦截器 applicationContext-tx-interceptor.xml 配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--引入配置文件属性-->
<!--<context:property-placeholder location="classpath:datasource.properties" />-->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:datasource.properties" />
</bean>
<!--配置数据源-->
<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="${jdbc.driver_class}"/>
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!--整合hibernate中sessionFactory 交给spring 容器管理-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" >
<property name="dataSource" ref="myDataSource" />
<property name="packagesToScan" value="com.aop.transaction.pay" />
<!--配置hibernate额外属性-->
<property name="hibernateProperties">
<props>
<!--设置hibernate方言-->
<!--<prop key="hibernate.dialect">org.hibernate.dialect.MySQL57Dialect</prop>-->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!--配置事物管理-->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 配置声明性事务管理(事务应用一般放在业务层) -->
<!-- 事务传播行为类型 说明 PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。 PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。 PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类
似的操作。 -->
<!-- aop代理 -->
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<!-- 设置事务管理其 -->
<property name="transactionManager" ref="transactionManager" />
<!--设置事物属性-->
<property name="transactionAttributes">
<props>
<!-- 设置拦截方法,可以使用通配符 -->
<!-- 可以设置事务的传播行为,隔离级别,多个值用逗号隔开 -->
<prop key="transfer*">PROPAGATION_REQUIRED,ISOLATION_REPEATABLE_READ</prop>
<prop key="add*">PROPAGATION_REQUIRED,ISOLATION_REPEATABLE_READ</prop>
<prop key="insert*">PROPAGATION_REQUIRED,ISOLATION_REPEATABLE_READ</prop>
</props>
</property>
</bean>
<!-- 定义BeanNameAutoProxyCreatorf进行Spring的事务处理 -->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!-- 针对指定的bean自动生成业务代理 -->
<property name="beanNames" value="*Service" />
<!-- 这个属性为true时,表示被代理的是目标类本身而不是目标类的接口[cglib] -->
<property name="proxyTargetClass">
<value>true</value>
</property>
<!-- 依赖注入上面定义的事务拦截器transactionInterceptor -->
<property name="interceptorNames">
<list>
<value>transactionInterceptor</value>
</list>
</property>
</bean>
<!--配置包扫描-->
<context:component-scan base-package="com.aop.transaction.pay" />
</beans>
注解 applicationContext-tx-annotation.xml 配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--引入配置文件属性-->
<!--<context:property-placeholder location="classpath:datasource.properties" />-->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:datasource.properties" />
</bean>
<!--配置数据源-->
<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="${jdbc.driver_class}"/>
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!--整合hibernate中sessionFactory 交给spring 容器管理-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean" >
<property name="dataSource" ref="myDataSource" />
<property name="packagesToScan" value="com.aop.transaction.pay" />
<!--配置hibernate额外属性-->
<property name="hibernateProperties">
<props>
<!--设置hibernate方言-->
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL57Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!--配置事物管理-->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 配置注解方式管理事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!--配置包扫描-->
<context:component-scan base-package="com.aop.transaction.pay" />
</beans>
测试代码: