事务管理的目的:
将若干sql语句作为一个整体 , 要么全部成功 , 要么全部失败!
事务套路:
就是在sql语句前后增加事务!
aop套路 :
就是将 目标代码 和 增强代码 进行 解耦(分离)
spring提供的事务管理分为两类:
一、编程式事务管理.(了解)
在需要事务管理目标代码中,添加事务管理的代码!
(有代码侵入事务管理方式 ,现在使用的非常少 )
缺点: 将目标代码和增强代码耦合在了一起 , 起不到aop的作用!
二、声明式事务管理.(重点)
底层使用AOP的环绕通知 , 没有任何代码侵入 .
(现在推荐使用)
声明式事务管理两种实现方式(XML和注解):
1.XML版-事务管理.
导入依赖jar包 : pom.xml ( 看最后 )
dao层接口: AccountDao.java
public interface AccountDao {
/**
* 出账
*/
public void out(String outName, double money) throws SQLException;
/**
* 入账
*/
public void in(String inName, double money) throws SQLException;
}
dao层实现类:AccountDaoImpl01.java
/**
* 使用xml版 , 对转账进行事务管理 .
*/
public class AccountDaoImpl01 extends JdbcDaoSupport implements AccountDao {
@Override
public void out(String outName, double money) throws SQLException {
String sql = "update account set money=money-? where name=?";
Object[] paramArr = {money, outName};
getJdbcTemplate().update(sql, paramArr);
}
@Override
public void in(String inName, double money) throws SQLException {
String sql = "update account set money=money+? where name=?";
Object[] paramArr = {money, inName};
getJdbcTemplate().update(sql, paramArr);
}
}
service层接口:
public interface AccountService {
/**
* 转账
*/
public void transfer(String outName, String inName, double money) throws SQLException;
}
service层实现类:
public class AccountServiceImpl01 implements AccountService {
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
public void transfer(String outName, String inName, double money) throws SQLException {
// 执行一组sql语句.
accountDao.out(outName, money);
// int i= 1/0;
accountDao.in(inName, money);
}
}
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_day01
jdbc.username=root
jdbc.password=root
Spring配置文件: applicationContext_dao.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">
<!-- 关联jdbc配置文件 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 将连接池交给spring处理 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 将dao交给spring -->
<bean id="accountDaoImpl01" class="com.jxj.dao.impl.AccountDaoImpl01">
<property name="dataSource" ref="dataSource" />
</bean>
</beans>
Spring配置文件: applicationContext_service.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: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/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">
<!-- 引入另一个配置文件 -->
<import resource="classpath:xml/applicationContext_dao.xml" />
<!-- 目标类: 将service交给spring -->
<bean id="accountServiceImpl01" class="com.jxj.service.impl.AccountServiceImpl01">
<property name="accountDao" ref="accountDaoImpl01" />
</bean>
<!-- 增强类: 使用事务管理器进行管理事务. -->
<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"/>
</tx:attributes>
</tx:advice>
<aop:config proxy-target-class="false" >
<aop:pointcut id="myPoint" expression="execution(* com.jxj.service..*.transfer(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="myPoint" />
</aop:config>
</beans>
测试类:
/**
* spring和junit进行整合.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:xml/applicationContext_service.xml"})
public class AccountServiceTest {
@Autowired
@Qualifier("accountServiceImpl01")
private AccountService accountService;
@Test
public void transfer() throws SQLException {
accountService.transfer("aaa","bbb",200);
}
}
2.注解版-事务管理
dao层接口: 同上.
dao层实现类: AccountDaoImpl02 .java
/**
* 使用注解版 , 对转账进行事务管理 .
*/
@Repository
public class AccountDaoImpl02 extends JdbcDaoSupport implements AccountDao {
// 根据类型注入连接池.
@Autowired
public void setDi(DataSource dataSource){
super.setDataSource(dataSource);
}
@Override
public void out(String outName, double money) throws SQLException {
String sql = "update account set money=money-? where name=?";
Object[] paramArr = {money, outName};
getJdbcTemplate().update(sql, paramArr);
}
@Override
public void in(String inName, double money) throws SQLException {
String sql = "update account set money=money+? where name=?";
Object[] paramArr = {money, inName};
getJdbcTemplate().update(sql, paramArr);
}
}
service层接口: 同上.
service层实现类: AccountServiceImpl02.java
@Service
public class AccountServiceImpl02 implements AccountService {
@Autowired
@Qualifier("accountDaoImpl02")
private AccountDao accountDao;
/**
给需要增强事务的方法 , 添加注解. (重点)
*/
@Transactional
public void transfer(String outName, String inName, double money) throws SQLException {
// 执行一组sql语句.
accountDao.out(outName, money);
// int i= 1/0;
accountDao.in(inName, money);
}
}
Spring配置文件: applicationContext_dao.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">
<!-- 关联jdbc配置文件 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 将连接池交给spring处理 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 通过扫描包的方式 , 将dao交给spring处理 -->
<context:component-scan base-package="com.jxj.dao" />
</beans>
Spring配置文件: applicationContext_service.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: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">
<!-- 引入外部配置文件 -->
<import resource="classpath:annotation/applicationContext_dao.xml" />
<!-- 目标类: service的实现类交给spring-->
<context:component-scan base-package="com.jxj.service" />
<!-- 增强类: spring提供的事务管理器. -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 通知spring扫描带有注解的方法. -->
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
测试类:
/**
* spring和junit进行整合.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:annotation/applicationContext_service.xml"})
public class AccountServiceTest {
@Autowired
@Qualifier("accountServiceImpl02")
private AccountService accountService;
@Test
public void transfer() throws SQLException {
accountService.transfer("aaa","bbb",200);
}
}
依赖: pom.xml
<dependencies>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
</dependencies>