声明式事务控制
编程式事务控制相关对象
PlatformTransactionManager
该对象是一个接口,提供了一系列控制事务的行为,具体的操作由不同的实现类决定。
TransactionDefination
事务的隔离级别
事务的传播行为
- REQUIRED_NEW:会开启一个新的事务,当出现异常会抛出一个异常,外面的事务会感知到,从而回滚。
- NESTED:对于外部事务来说,本事务是外部事务的子事务,外部事物回滚,子事务也会回滚,当子事务回滚,外部事物会感知到,如果用try…catch块处理了,外部的事务就不会回滚。
TransactionStatus
基于XML的声明式事务控制
什么是声明式事务控制
声明式事务处理的作用
环境搭建
1.dao层
package cn.zhw.tx.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class AccountDaoImpl implements AccountDao{
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void out(String outMan, Integer money) {
jdbcTemplate.update("update account set money = money -? where name = ?",money,outMan);
}
@Override
public void in(String inMan, Integer money) {
jdbcTemplate.update("update account set money = money + ? where name = ?",money,inMan);
}
}
2.service层
package cn.zhw.tx.service;
import cn.zhw.tx.dao.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AccountServiceImpl implements AccountService{
@Autowired
private AccountDao accountDao;
@Override
public void transfer(String outMan, String inMan, Integer money) {
//扣钱
accountDao.out(outMan,money);
//加钱
accountDao.in(inMan,money);
}
}
3.javaBean
package cn.zhw.tx.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {
private String name;
private Integer money;
}
4.配置文件
<?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">
<!-- 将db.properties中的键值对加入到springIco的容器中-->
<context:property-placeholder location="classpath:db.properties"/>
<context:component-scan base-package="cn.zhw.tx">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
<!-- 配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${jdbc.username}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置springJdbc Template-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
5.测试
package cn.zhw.tx.test;
import cn.zhw.tx.service.AccountService;
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(locations = {"classpath:applicationContext.xml"})
public class TxTest {
@Autowired
private AccountService accountService;
@Test
public void test1(){
accountService.transfer("zhengshihao","xiaohong",5);
}
}
配置事务
<?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"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
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">
<!-- 将db.properties中的键值对加入到springIco的容器中-->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 扫描service和dao层加入到容器中-->
<context:component-scan base-package="cn.zhw.tx">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
<!-- 配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${jdbc.username}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置springJdbc Template-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置平台事务管理器,当底层使用的不是原始的jdbc需要更改-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 通知 事务的增强-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="transfer" timeout="1" read-only="false" isolation="DEFAULT" propagation="REQUIRED"/>
<tx:method name="save" timeout="1" read-only="false" isolation="DEFAULT" propagation="REQUIRED"/>
<!-- update开头的方法-->
<tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT" timeout="1"/>
<!-- 默认的事务控制,代表任意方法-->
<tx:method name="*" />
</tx:attributes>
</tx:advice>
<!-- 配置事务的织入关系-->
<aop:config>
<aop:pointcut id="pot1" expression="execution(* cn.zhw.tx.service.AccountServiceImpl.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pot1"/>
</aop:config>
</beans>
事务配置详解
基于注解的事务控制
1.开启注解配置
<?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"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
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">
<!-- 将db.properties中的键值对加入到springIco的容器中-->
<context:property-placeholder location="classpath:db.properties"/>
<context:component-scan base-package="cn.zhw.tx">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
<!-- 配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="username" value="${jdbc.username}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置springJdbc Template-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置平台事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置注解驱动事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
2.在service层配置事务
package cn.zhw.tx.service;
import cn.zhw.tx.dao.AccountDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
@Service
//配置在类上,会对该类中的所有方法都起作用
//@Transactional(isolation = Isolation.DEFAULT)
public class AccountServiceImpl implements AccountService{
@Autowired
private AccountDao accountDao;
@Override
@Transactional(isolation = Isolation.DEFAULT)
public void transfer(String outMan, String inMan, Integer money) {
//扣钱
accountDao.out(outMan,money);
//自杀式错误
// int i =10/0;
//加钱
accountDao.in(inMan,money);
}
}
3.注意
所有的组件都必须由spring管理,基于注解的配置才能使用