Spring 为编程式的事务管理,提供了相应的模板类 org.springframework.transaction.support.TransactionTemplate,能够应对一些特殊场合的须要。mysql
TransactionTemplate 是线程安全的,因此能够在多个类中共享 TransactionTemplate 实例,实现事务管理 。spring
TransactionTemplate 继承了 DefaultTransactionDefinition,因此也拥有多种设置事务属性的方法:sql
TransactionTemplate 类的主要方法:apache
方法 | 说明 |
---|---|
public void setTransactionManager(PlatformTransactionManager transactionManager) |
设置事务管理器。 |
public <T> T execute(TransactionCallback<T> action) |
在 TransactionCallback 回调接口中,编写须要以事务方式执行的数据访问逻辑代码。 |
TransactionCallback 接口只定义了一个方法 doInTransaction(TransactionStatus status)
。Spring 还定义了一个抽象类 TransactionCallbackWithoutResult,用于只执行,但不须要返回结果的场景。编程
Spring 配置文件:安全
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 扫描包含注解定义的类包-->
<context:component-scan base-package="net.deniro.xxx.transaction"/>
<!-- 数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://127.0.0.1:3306/xxx"
p:username="root"
p:password="xxx"/>
<!-- JDBC 模板-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="dataSource"
/>
<!-- 事务管理器-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource"/>
<!-- 事务模板 -->
<bean id="TransactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate"
p:transactionManager-ref="transactionManager"/>
</beans>
复制代码
User 类:bash
public class User {
private long id;
private String name;
public User(String name) {
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
复制代码
UserDao 类:ide
@Repository
public class UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
/**
* 保存帐号
*
* @param user
* @throws SQLException
*/
public void save(User user) {
String sql = "insert into t_user(user_name) values(?)";
jdbcTemplate.update(sql, user.getName());
String sql2 = "insert into t_log(user_name) values(?)";
jdbcTemplate.update(sql2, user.getName());
}
}
复制代码
为了实验事务是否生效,这里的第一个 SQL 是正确的,而第二个 SQL 是错误的(找不到表)。单元测试
UserService 类:测试
@Service
public class UserService {
@Autowired
private UserDao userDao;
@Autowired
private TransactionTemplate template;
public void save(final User user) {
template.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
userDao.save(user);
}
});
}
}
复制代码
单元测试:
public class UserServiceTest {
ApplicationContext context;
@BeforeMethod
public void setUp() throws Exception {
context = new ClassPathXmlApplicationContext("spring.xml");
}
@Test
public void test() {
UserService userService = (UserService) context.getBean("userService");
final User user = new User("deniro");
userService.save(user);
}
}
复制代码
为了看到 Spring 的事务日志,咱们能够修改 log4j 事务配置,级别改成 DEBUG:
log4j.logger.org.springframework.jdbc.datasource.DataSourceTransactionManager=DEBUG
log4j.logger.org.springframework.transaction.interceptor=DEBUG
log4j.logger.org.springframework.transaction=DEBUG
复制代码
运行结果分析:
Spring 首先建立一个新的事务。
在执行到第二个 SQL 语句时,抛出异常;Spring 执行回滚操做。说明事务生效咯O(∩_∩)O~