1. Spring 事务的三大组件
Spring 事务管理高层抽象主要包括3个接口
PlatformTransactionManager : 事务管理器
TransactionDefinition : 事务定义信息(隔离,传播,超时,只读)
TransactionStatus :事务具体运行状态
在事务定义信息中 有四种定义了
事务的是否只读 : 当前要执行的代码是否应用到事务,如果事务是只读的话不会用到事务的只读控制 ( readonly )
事务的隔离级别 : 四种隔离级别
事物的传播行为 : 事物的嵌套问题
事务的超时时间 : 默认为-1 永不超时
2. Spring 事务管理
Spring 支持两种方式事务管理
编程式的事务管理
使用XML配置声明式事务
2.1 编程式:
配置我们的工厂bean2.xml
<context:component-scan base-package="trans"></context:component-scan>
<!--扫描外部的配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!--数据库连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--配置jdbctemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></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>
配置jdbctemplate 中的 jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc\:mysql\://localhost\:3306/···
jdbc.username=···
jdbc.password=···
创建一个Dao
@Repository
public class AccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
//进账
public void intMoney(String account,int money){
jdbcTemplate.update("update account set money=money+? where name=?",money,account);
}
//出账
public void outMoney(String account,int money){
jdbcTemplate.update("update account set money=money-? where name=?",money,account);
}
创建一个Service
@Service
public class AccountService {
@Autowired
private AccountDao accountDao;
@Autowired
private TransactionTemplate transactionTemplate;
public void transfer(){
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
accountDao.intMoney("aaa",100);
//有异常 不会进行转账
int i=1/0;
accountDao.outMoney("bbb",100);
}
});
}
测试
public class TextTrans {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("bean2.xml");
AccountService accountService = applicationContext.getBean(AccountService.class);
accountService.transfer();
}
}
account 表:
2.2 使用XML配置声明式事务(原始方式)
配置我们的工厂bean2.xml
<context:component-scan base-package="trans"></context:component-scan>
<!--扫描外部的配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!--数据库连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--配置jdbctemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></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="accountServiceTrans" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!--事务管理器-->
<property name="transactionManager" ref="transactionManager"></property>
<!--为哪个类设置代理信息-->
<property name="target" ref="accountService"></property>
<!--事务的定义信息-->
<property name="transactionAttributes" >
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
配置jdbctemplate 中的 jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc\:mysql\://localhost\:3306/···
jdbc.username=···
jdbc.password=···
创建一个Dao
@Repository
public class AccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
//进账
public void intMoney(String account,int money){
jdbcTemplate.update("update account set money=money+? where name=?",money,account);
}
//出账
public void outMoney(String account,int money){
jdbcTemplate.update("update account set money=money-? where name=?",money,account);
}
}
创建一个Service
@Service
public class AccountService {
@Autowired
private AccountDao accountDao;
public void transfer(){
accountDao.intMoney("aaa", 100);
int i = 1 / 0;
accountDao.outMoney("bbb", 100);
}
}
测试
public class TextTrans {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("bean2.xml");
AccountService accountServiceTrans = (AccountService) applicationContext.getBean("accountServiceTrans");
accountServiceTrans.transfer();
}
}
2.3 使用XML配置声明式事务(基于tx/aop)
配置我们的工厂beanAop.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"
xmlns:aop="http://www.springframework.org/schema/aop"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="transAop"></context:component-scan>
<!--扫描外部的配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!--数据库连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--配置jdbctemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--基于tx/aop的方式配置事务增强-->
<tx:advice id="interceptor" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="find*" read-only="true"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="*" read-only="false"/>
</tx:attributes>
</tx:advice>
<!--基于tx/aop的方式配置切面-->
<aop:config>
<!--切面-->
<aop:pointcut id="point" expression="execution(* transAop..*(..))"/>
<!--增强-->
<aop:advisor advice-ref="interceptor" pointcut-ref="point"></aop:advisor>
</aop:config>
</beans>
创建一个Dao
@Repository
public class AccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
//进账
public void intMoney(String account,int money){
jdbcTemplate.update("update account set money=money+? where name=?",money,account);
}
//出账
public void outMoney(String account,int money){
jdbcTemplate.update("update account set money=money-? where name=?",money,account);
}
}
创建一个Service
@Service
public class AccountService {
@Autowired
private AccountDao accountDao;
public void transfer(){
accountDao.intMoney("aaa", 100);
// int i = 1 / 0;
accountDao.outMoney("bbb", 100);
}
}
测试:
public class TextTrans {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("beanAop.xml");
AccountService accountService = applicationContext.getBean(AccountService.class);
accountService.transfer();
}
}
2.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"
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">
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
<context:component-scan base-package="transZJ"></context:component-scan>
<!--扫描外部的配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!--数据库连接池-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--配置jdbctemplate-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
@Repository
public class AccountDao {
@Autowired
private JdbcTemplate jdbcTemplate;
void intMoney(String account,int money){
jdbcTemplate.update("update account set money=money+? where name=?",money,account);
}
void outMoney(String account,int money){
jdbcTemplate.update("update account set money=money-? where name=?",money,account);
}
}
@Service
@Transactional //注意
public class AccountService {
@Autowired
private AccountDao accountDao;
public void transfer(){
accountDao.intMoney("aaa",100);
// int i=1/0;
accountDao.outMoney("bbb",100);
}
}
public class TextZJ {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext =
new ClassPathXmlApplicationContext("beanZJ.xml");
AccountService accountService = applicationContext.getBean(AccountService.class);
accountService.transfer();
}
}