一、事务管理器
事务管理器.png
二、事务的传播规则
Spring 在 TransactionDefinition 接口中定义了七种事务传播规则,规定了事务方法和事务方法发生嵌套调用时事务如何进行传播
- PROPAGATION_REQUIRED:若当前没有事务,则新建一个事务,若当前已存在一个事务,则加入到该事务中(最常用操作)。
- PROPAGATION_SUPPORTS:支持当前事务,若当前没有事务,则以非事务方式执行
- PROPAGATION_MANDATORY:使用当前事务,若当前没有事务,则抛出异常
- PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起
- PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,若当前存在事务,则把当前事务挂起
- PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常
- PROPAGATION_NESTED:如当前存在事务,则嵌套在本事务内执行,若没有事务则执行PROPAGATION_REQUIRED类似操作
三、在 applicationContext.xml 中引入事务环境
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
</beans>
四、转账示例
- domain
package com.revanwang.tx.domain;
import lombok.Data;
@Data
public class Account {
private Long id;
private Double balance;
}
- dao
package com.revanwang.tx.dao.impl;
import com.revanwang.tx.dao.IAccountDAO;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
public class AccountDAOImpl implements IAccountDAO {
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public void bankIn(Long inId, Double money) {
String sql = "UPDATE Account SET balance = balance + ? WHERE id = ?";
this.jdbcTemplate.update(sql, money, inId);
}
@Override
public void bankOut(Long outId, Double money) {
String sql = "UPDATE Account SET balance = balance - ? WHERE id = ?";
this.jdbcTemplate.update(sql, money, outId);
}
}
- service
package com.revanwang.tx.service.impl;
import com.revanwang.tx.dao.IAccountDAO;
import com.revanwang.tx.service.IAccountService;
import lombok.Setter;
public class AccountServiceImpl implements IAccountService {
@Setter
private IAccountDAO accountDAO;
@Override
public void bankTrans(Long inId, Long outId, Double money) {
this.accountDAO.bankIn(inId, money);
System.out.println(1 / 0);
this.accountDAO.bankOut(outId, money);
}
}
- AccountTest
package com.revanwang.tx;
import com.revanwang.tx.action.AccountAction;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AccountTest {
@Autowired
private AccountAction accountAction;
@Test
public void testTrans() {
this.accountAction.bankTrans(10086L, 10010L, (double) 550);
}
}
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<!-- what:配置事务类型 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataBaseDB"/>
</bean>
<!-- when:当在什么时候做增强 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="bankTrans"/>
</tx:attributes>
</tx:advice>
<!-- where:在哪些包下的类型中的哪些方法上做增强 -->
<aop:config>
<!--切入点-->
<aop:pointcut id="txPoint" expression="execution(* com.revanwang.tx.service.*Service.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"/>
</aop:config>
<!-- 引入属性配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!--配置缓冲池-->
<bean id="dataBaseDB" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="url" value="${jdbc.url}"/>
<property name="maxActive" value="${jdbc.maxActive}"/>
</bean>
<!--配置DAO-->
<bean id="accountDAO" class="com.revanwang.tx.dao.impl.AccountDAOImpl">
<property name="dataSource" ref="dataBaseDB"/>
</bean>
<!--配置Service-->
<bean id="accountService" class="com.revanwang.tx.service.impl.AccountServiceImpl">
<property name="accountDAO" ref="accountDAO"/>
</bean>
<!--配置Action-->
<bean id="accountAction" class="com.revanwang.tx.action.AccountAction">
<property name="accountService" ref="accountService"/>
</bean>
</beans>

五、转账示例注解
- applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<!-- what:配置事务类型 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataBaseDB"/>
</bean>
<tx:annotation-driven transaction-manager="txManager"/>
<!-- 引入属性配置文件 -->
<context:property-placeholder location="classpath:db.properties"/>
<!--配置缓冲池-->
<bean id="dataBaseDB" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="url" value="${jdbc.url}"/>
<property name="maxActive" value="${jdbc.maxActive}"/>
</bean>
<!--配置DAO-->
<bean id="accountDAO" class="com.revanwang.tx.dao.impl.AccountDAOImpl">
<property name="dataSource" ref="dataBaseDB"/>
</bean>
<!--配置Service-->
<bean id="accountService" class="com.revanwang.tx.service.impl.AccountServiceImpl">
<property name="accountDAO" ref="accountDAO"/>
</bean>
<!--配置Action-->
<bean id="accountAction" class="com.revanwang.tx.action.AccountAction">
<property name="accountService" ref="accountService"/>
</bean>
</beans>
- service
package com.revanwang.tx.service.impl;
import com.revanwang.tx.dao.IAccountDAO;
import com.revanwang.tx.service.IAccountService;
import lombok.Setter;
import org.springframework.transaction.annotation.Transactional;
@Transactional
public class AccountServiceImpl implements IAccountService {
@Setter
private IAccountDAO accountDAO;
@Override
public void bankTrans(Long inId, Long outId, Double money) {
this.accountDAO.bankIn(inId, money);
System.out.println(1 / 0);
this.accountDAO.bankOut(outId, money);
}
}
网友评论