Spring事务管理高级应用难点剖析,第1部分
时间:2012-04-26 IBM 陈雄华
概述
Spring 最成功,最吸引人的地方莫过于轻量级的声明式事务管理,仅此一点,它就宣告了 重量级 EJB 容器的覆灭。Spring 声明式事务管理将开发者从繁复的事务管理代码中解脱出来 ,专注于业务逻辑的开发上,这是一件可以被拿来顶礼膜拜的事情。但是,世界并未从此消停 ,开发人员需要面对的是层出不穷的应用场景,这些场景往往逾越了普通 Spring 技术书籍的 理想界定。因此,随着应用开发的深入,在使用经过 Spring 层层封装的声明式事务时,开发 人员越来越觉得自己坠入了迷雾,陷入了沼泽,体会不到外界所宣称的那种畅快淋漓。本系列 文章的目标旨在整理并剖析实际应用中种种让我们迷茫的场景,让阳光照进云遮雾障的山头。
DAO 和事务管理的牵绊
很少有使用 Spring 但不使用 Spring 事务管理器的应用,因此常常有人会问:是否用了 Spring,就一定要用 Spring 事务管理器,否则就无法进行数据的持久化操作呢?事务管理器 和 DAO 是什么关系呢?
也许是 DAO 和事务管理如影随行的缘故吧,这个看似简单的问题实实在在地存在着,从初 学者心中涌出,萦绕在开发老手的脑际。答案当然是否定的!我们都知道:事务管理是保证数 据操作的事务性(即原子性、一致性、隔离性、持久性,也即所谓的 ACID),脱离了事务性, DAO 照样可以顺利地进行数据的操作。
下面,我们来看一段使用 Spring JDBC 进行数据访问的代码:
清单 1. UserJdbcWithoutTransManagerService.java
package user.withouttm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.apache.commons.dbcp.BasicDataSource;
@Service("service1")
public class UserJdbcWithoutTransManagerService {
@Autowired
private JdbcTemplate jdbcTemplate;
public void addScore(String userName,int toAdd){
String sql = "UPDATE t_user u SET u.score = u.score + ? WHERE user_name =?";
jdbcTemplate.update(sql,toAdd,userName);
}
public static void main(String[] args) {
ApplicationContext ctx =
new ClassPathXmlApplicationContext ("user/withouttm/jdbcWithoutTransManager.xml");
UserJdbcWithoutTransManagerService service =
(UserJdbcWithoutTransManagerService)ctx.getBean("service1");
JdbcTemplate jdbcTemplate = (JdbcTemplate)ctx.getBean ("jdbcTemplate");
BasicDataSource basicDataSource = (BasicDataSource) jdbcTemplate.getDataSource();
//①.检查数据源autoCommit的设置
System.out.println("autoCommit:"+ basicDataSource.getDefaultAutoCommit());
//②.插入一条记录,初始分数为10
jdbcTemplate.execute(
"INSERT INTO t_user(user_name,password,score) VALUES (''tom'',''123456'',10)");
//③.调用工作在无事务环境下的服务类方法,将分数添加20分
service.addScore("tom",20);
//④.查看此时用户的分数
int score =
|