目录
创建一个数据表,有a,b两个数据,a,b各有2000元
若a向b转100,则现在a为1900,b为2100
此时在Spring事务管理
创建com.mz.mapper.UserMapper接口
public interface UserMapper {
public void decrease(Integer id, Double money);//转出
public void increase(Integer id, Double money);//转入
}
创建com.mz.mapper.impl.UserMapperImpl
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
public void setUserMapper(UserMapper userMapper){
this.userMapper = userMapper;
}
@Override
public void transfer(Integer fromId, Integer toId, Double money) {
userMapper.decrease(fromId,money);//转出
userMapper.increase(toId,money);//转入
}
}
创建com.mz.service.UserService接口
public interface UserService {
//转账
public void transfer(Integer fromId,Integer toId,Double money);
}
创建com.mz.service.impl.UserSServcieImpl类实现上面接口
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
public void setUserMapper(UserMapper userMapper){
this.userMapper = userMapper;
}
@Override
public void transfer(Integer fromId, Integer toId, Double money) {
userMapper.decrease(fromId,money);//转出
userMapper.increase(toId,money);//转入
}
}
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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here -->
<!-- 引入配置文件-->
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!-- 引入数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${db.username}"></property>
<property name="password" value="${db.password}"></property>
<property name="url" value="${db.url}"></property>
<property name="driverClassName" value="${db.driverClassName}"></property>
</bean>
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<bean id="userMapper" class="com.mz.mapper.impl.UserMapperImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="userService" class="com.mz.service.impl.UserServiceImpl">
<property name="userMapper" ref="userMapper"></property>
</bean>
</beans>
创建测试类实现
public class test {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
UserService userService =
(UserService)applicationContext.getBean("userService");
userService.transfer(1,2,100d);
}
}
此时出现结果为:
a为1900,b为2100,现在是正常的流程,但如果在a给b转账的时候出现意外
就如这种状况,此时运行程序,会出现:
你会发现,转出的方法执行,转入的未执行,即a减少100元,但b没有变化 ,因此我们需要一个方法解决这种错误。
这时候的话就需要给它搭配一个事务。在Spring中给我们提供两种方式
1.编程式事务管理(手动编写代码完成事务管理):
com.mz.service.impl.UserServiceimpl类
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
public void setUserMapper(UserMapper userMapper){
this.userMapper = userMapper;
}
//事务模板对象
private TransactionTemplate transactionTemplate;
public void setTransactionTemplate(TransactionTemplate transactionTemplate){
this.transactionTemplate = transactionTemplate;
}
// @Override
// public void transfer(Integer fromId, Integer toId, Double money) {
// userMapper.decrease(fromId,money);//转出
// int i = 1/0;
// userMapper.increase(toId,money);//转入
// }
@Override
public void transfer(final Integer fromId, final Integer toId, final Double money) {
//手动编程式事务(了解)
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
userMapper.decrease(fromId, money);//转出
//int i = 1 / 0;
userMapper.increase(toId, money);//转入
}
});
}
}
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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- bean definitions here -->
<!-- 引入配置文件-->
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!-- 引入数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${db.username}"></property>
<property name="password" value="${db.password}"></property>
<property name="url" value="${db.url}"></property>
<property name="driverClassName" value="${db.driverClassName}"></property>
</bean>
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<!-- 事务平台管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 事务模板对象-->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<bean id="userMapper" class="com.mz.mapper.impl.UserMapperImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="userService" class="com.mz.service.impl.UserServiceImpl">
<property name="userMapper" ref="userMapper"></property>
<property name="transactionTemplate" ref="transactionTemplate"></property>
</bean>
</beans>
此时,a为1800,b为2100
若正常运行,,a为1700,b为2200。
若发生异常,,此时,方法都不执行。
2.声明式事务管理(不需要手动编写代码,配置):
1)Xml配置(aop)的方式完成事务管理
com.mz.service.impl.UserServiceImpl
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
public void setUserMapper(UserMapper userMapper){
this.userMapper = userMapper;
}
@Override
public void transfer(Integer fromId, Integer toId, Double money) {
userMapper.decrease(fromId,money);//转出
//int i = 1/0;
userMapper.increase(toId,money);//转入
}
}
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/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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here -->
<!-- 引入配置文件-->
<context:property-placeholder location="classpath:db.properties"></context:property-placeholder>
<!-- 引入数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${db.username}"></property>
<property name="password" value="${db.password}"></property>
<property name="url" value="${db.url}"></property>
<property name="driverClassName" value="${db.driverClassName}"></property>
</bean>
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<!-- 事务平台管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>
<tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 配置事务切面-->
<aop:config>
<aop:pointcut id="txPc" expression="execution(* com.qf.service.impl.*ServiceImpl.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"></aop:advisor>
</aop:config>
<!-- <!– 事务模板对象–>-->
<!-- <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">-->
<!-- <property name="transactionManager" ref="transactionManager"></property>-->
<!-- </bean>-->
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<bean id="userMapper" class="com.mz.mapper.impl.UserMapperImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="userService" class="com.mz.service.impl.UserServiceImpl">
<property name="userMapper" ref="userMapper"></property>
<!-- <property name="transactionTemplate" ref="transactionTemplate"></property>-->
</bean>
</beans>
此时a为1700,b为2200
正常运行,则,a为1600,b为2300。
异常运行,则,a,b不变,方法不执行。
2)注解配置(aop)的方式完成事务管理
com.mz.service.impl.UserServletImpl
@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = true)
public class UserServiceImpl implements UserService {
private UserMapper userMapper;
public void setUserMapper(UserMapper userMapper){
this.userMapper = userMapper;
}
@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.REQUIRED,readOnly = false)
@Override
public void transfer(Integer fromId, Integer toId, Double money) {
userMapper.decrease(fromId,money);//转出
int i = 1/0;
userMapper.increase(toId,money);//转入
}
}
applictionContext.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/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:db.properties"></context:property-placeholder>
<!-- 引入数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${db.username}"></property>
<property name="password" value="${db.password}"></property>
<property name="url" value="${db.url}"></property>
<property name="driverClassName" value="${db.driverClassName}"></property>
</bean>
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<!-- 事务平台管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启注解配置事务-->
<tx:annotation-driven></tx:annotation-driven>
<!--********************************************************************************************************************-->
<!-- 配置事务通知 -->
<!-- <tx:advice id="txAdvice" transaction-manager="transactionManager">-->
<!-- <tx:attributes>-->
<!-- <tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false"/>-->
<!-- <tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true"/>-->
<!-- </tx:attributes>-->
<!-- </tx:advice>-->
<!-- <!– 配置事务切面–>-->
<!-- <aop:config>-->
<!-- <aop:pointcut id="txPc" expression="execution(* com.mz.service.impl.*ServiceImpl.*(..))"/>-->
<!-- <aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"></aop:advisor>-->
<!-- </aop:config>-->
<!--*******************************************************************************************************************-->
<!-- <!– 事务模板对象–>-->
<!-- <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">-->
<!-- <property name="transactionManager" ref="transactionManager"></property>-->
<!-- </bean>-->
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<!-- ———————————————————————————————————————————————————————————————————————————————————————————————————————————————— -->
<bean id="userMapper" class="com.mz.mapper.impl.UserMapperImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="userService" class="com.mz.service.impl.UserServiceImpl">
<property name="userMapper" ref="userMapper"></property>
<!-- <property name="transactionTemplate" ref="transactionTemplate"></property>-->
</bean>
</beans>
此时a为1600,b为2300
正常运行,则,a为1500,b为2400。
出现异常的话则,a,b方法不执行。
3.pox.xml中的相关依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.10</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.3.10</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.10</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>