什么是事务?
事务是指一组逻辑上的操作,这些操作要么都失败,要么都成功。
事务的特性
- 原子性:事务中所有的操作,要么都成功,要么都失败。
- 隔离性:在多个用户访问中,每一个用户的事务都不受其它用户事务的干扰。
- 完整性:事务提交前后,数据必须一致。
- 持久性:事务一旦提交,对数据库的修改是永久的,即便电脑发生故障,也不会对数据造成影响。
spring的事务管理方式
事务管理常用接口
PlateformTransactionManager:事务管理器
TransactionDefinition:事务定义信息(传播行为、隔离级别、是否只读、超时信息等)
TransactionStatus:事务运行的状态
编程式事务管理(少用)
- 第一步:配置文件中定义事务管理器
- 第二步:配置文件中定义TransactionTemplate类信息,并将事务管理器注入到TransactionTemplate类中
- 第三步:在需要使用事务的类中,添加TransactionTemplate类的属性并注入。
- 第四步:在需要使用事务的方法中调用TransactionTemplate的execute方法,使用事务(需要用到TransactionCallbackWithoutResult类,可以使用匿名内部类)。
代码如下:
/**
* 转账业务类
*/
public interface UserService {
/**
* 转账操作
* @param out :转出金额账户
* @param in :转入金额账户
* @param money :转账金额
*/
public void transfer(String out, String in, Double money);
}
/**
* 转账业务实现类
*/
public class UserServiceImpl implements UserService {
private UserDao userDao;
private TransactionTemplate transactionTemplate;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
/**
* 转账操作
* @param out :转出金额账户
* @param in :转入金额账户
* @param money :转账金额
*/
@Override
public void transfer(String out, String in, Double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
userDao.out(out, money);
int i = 1/0;
userDao.in(in, money);
}
});
}
}
/**
* 转账持久类
*/
public interface UserDao {
/**
* 转出金额
* @param out: 转出金额账户
* @param money:转出金额
*/
public void out(String out, Double money);
/**
* 转入金额
* @param in: 转入金额账户
* @param money:转入金额
*/
public void in(String in, Double money);
}
/**
* 转账持久层实现类:使用Spring中的JdbcTemplate模板实现持久层
*/
public class UserDaoImpl implements UserDao {
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
* 转出金额
* @param out: 转出金额账户
* @param money:转出金额
*/
@Override
public void out(String out, Double money) {
String sql = "update account set money = money - ? where name = ?";
jdbcTemplate.update(sql, money, out);
}
/**
* 转入金额
* @param in: 转入金额账户
* @param money:转入金额
*/
@Override
public void in(String in, Double money) {
String sql = "update account set money = money + ? where name = ?";
jdbcTemplate.update(sql, money, in);
}
}
applicationContext.xml内部如下:
<!-- 引入jdbc Properties文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClass}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置 JdbcTemplate 模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="userService" class="com.spring.transaction.demo1.UserServiceImpl">
<property name="userDao" ref="userDao"/>
<property name="transactionTemplate" ref="transactionTemplate"/>
</bean>
<bean id="userDao" class="com.spring.transaction.demo1.UserDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</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>
声明式事务管理
接口和dao的实现类都是相同的代码,就不重复贴了。
基于TransactionProxyFactoryBean类的声明式事务管理(很少用)
具体代码如下:
/**
* 转账业务实现类
*/
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
/**
* 转账操作
* @param out :转出金额账户
* @param in :转入金额账户
* @param money :转账金额
*/
@Override
public void transfer(String out, String in, Double money) {
userDao.out(out, money);
int i = 1/0;
userDao.in(in, money);
}
}
applicationContext.xml如下:
<!-- 引入jdbc Properties文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClass}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置 JdbcTemplate 模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="userService" class="com.spring.transaction.demo2.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.spring.transaction.demo2.UserDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置增强类 -->
<bean id="transactionProxyFatoryBean" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="target" ref="userService"/>
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="transfer">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
基于AspectJ的xml配置事务管理
具体代码如下:
/**
* 转账业务实现类
*/
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
/**
* 转账操作
* @param out :转出金额账户
* @param in :转入金额账户
* @param money :转账金额
*/
@Override
public void transfer(String out, String in, Double money) {
userDao.out(out, money);
// int i = 1/0;
userDao.in(in, money);
}
}
applicationContext.xml如下:
<!-- 引入jdbc Properties文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClass}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置 JdbcTemplate 模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="userService" class="com.spring.transaction.demo3.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.spring.transaction.demo3.UserDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</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" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置切面 -->
<aop:config>
<aop:pointcut expression="execution(* com.spring.transaction.demo3.*.*(..))" id="transactionAspect"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="transactionAspect"/>
</aop:config>
基于注解的事务管理
具体代码如下:
/**
* 转账业务实现类
*/
@Transactional(propagation=Propagation.REQUIRED)
public class UserServiceImpl implements UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
/**
* 转账操作
* @param out :转出金额账户
* @param in :转入金额账户
* @param money :转账金额
*/
@Override
public void transfer(String out, String in, Double money) {
userDao.out(out, money);
int i = 1/0;
userDao.in(in, money);
}
}
applicationContext.xml如下:
<!-- 引入jdbc Properties文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driverClass}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 配置 JdbcTemplate 模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="userService" class="com.spring.transaction.demo4.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.spring.transaction.demo4.UserDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 启用事务注解 -->
<tx:annotation-driven/>
jdbc.properties如下:
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc\:mysql\://localhost\:3306/test
jdbc.username=root
jdbc.password=