事务使用分析经验总结
来源:互联网 发布:服务器端口是多少 编辑:程序博客网 时间:2024/05/21 22:56
前段时间版本开发中,同事问我,为什么他的功能没有事务回滚,由于事务问题一直在项目中存在,今天抽空了解决了该问题,下面是分析结果
分析过程是这样的:
1.模拟当时没有事务回滚的代码写了个测试代码
在xhttp层的user类中加了个testtran方法
在facade层的user类中加了个facadetran方法和servicetran方法,facadetran方法调用servicetran方法
在service层的user类中加了个testtran方法,里面有更新和插入操作
配置applicationcontext-datasource.xml文件,关键代码
在配置中对facadetran和servicetran方法都进行了拦截。
配置application-facade.xml文件,这个同以前的配置是一样的,主要是用于事务控制的
框中部分就是最基本的spring事务配置,这里就不说了
2.测试结果
1.去掉facade* 这个匹配项,则事务不启作用,虽然有service *的匹配项
2.加上facade* 这个匹配项,有事务
3.结果分析
这是有事务时的当前本地变量中存的connection连接对象
start=10437382(oracle.jdbc.driver.OracleConnection@1e9445c) --facade 的facadetran打印的
start service=10437382(oracle.jdbc.driver.OracleConnection@1e9445c) --facade 的servicetran打印的
updateTrance=10437382(oracle.jdbc.driver.OracleConnection@1e9445c) --dao层打印的
addTrance=10437382(oracle.jdbc.driver.OracleConnection@1e9445c) --dao层打印的
end service=10437382(oracle.jdbc.driver.OracleConnection@1e9445c) --facade 的servicetran打印的
end=10437382(oracle.jdbc.driver.OracleConnection@1e9445c) ----facade 的facadetran打印的
所有的connection对象是一样的,因此保证了事务
这是没有事务时的当前本地变量中存的connection连接对象
start=5067839(oracle.jdbc.driver.OracleConnection@d62eb9) --facade 的facadetran打印的
start service=26067327(oracle.jdbc.driver.OracleConnection@19a7cb8) --facade 的servicetran打印的
updateTrance=11042980(oracle.jdbc.driver.OracleConnection@959dae) --dao层打印的
addTrance=31319257(oracle.jdbc.driver.OracleConnection@db6fd3) --dao层打印的
end service=27130714(oracle.jdbc.driver.OracleConnection@e10f10) --facade 的servicetran打印的
end=25340210(oracle.jdbc.driver.OracleConnection@1323b6c) ----facade 的facadetran打印的
每个connection对象都不一样,因此没有了事务
4.结论:
如果需要事务,请在最外层调入facade层时的方法时做事务,如facadeTran,而后面过滤到的也是没用的。因此这个开发时一定要注意,如果还是没有事务,可以直接打印当前的
连接对象是不是正确的
5.spring事务是这样实现的?
理解这个也对我们找问题也是有帮助的,假设如果我们自已实现一个事务也是可以的,spring也只是借助数据库来回滚的。
a.得到一个连接conn
b.把事务改成手动conn.setAutoCommit(false)
c.数据库相关业务操作
d.提交conn.commit();
e.如果业务失败,则在异常中comm.rollback();
f.最后需要在finally关闭连接
因此如果几个业务需要同时提交时必须在一个连接的原因了,spring只不过在这个流程中穿了个外套而已,呵呵
6.spring的事务传播行为介绍
7.问题补充
......
String[] arr = str.split(",");
try
{
getSqlMapClient().startTransaction();
getSqlMapClient().startBatch();
for (int i = 0; i < 3; i++)
{
String serid = arr[0];
String name = arr[1];
Map<String, String> map = new HashMap<String, String>();
map.put("serid", serid + new Random().nextInt(10000));
map.put("name", name);
System.out.println("addTrance="
+ this.getDataSource().getConnection());
getSqlMapClient().insert("AppInfoFor139.add", map);
}
getSqlMapClient().executeBatch();
getSqlMapClient().commitTransaction();
}
catch (SQLException e)
{
throw new SepException(ErrorCode.INSERT_EXCEPTION, true, e);
}
....
象这种批处理,如果在facade打开了事务,这里手动设置也是无效的,因此需要注意这种需要手动提交的,就不能在facade开启事务了
8.开发建议
开发上面需要做下规范
1、不能在接口层进行for循环调用facade层的方法,特别是做了事务代理的方法。这样从facade层就获取了一个db的connection。大量的组装url for循环调用导致了业务向数据库发了大量的获取连接和释放连接的不需要的开销)
2、facade层定义的方法如果涉及到数据库操作且需要进行事务处理,需要和spring的bin定义文件中的事务代理类的add*之类的正则表达式一致。
以上如果有错误,请大牛们纠正,呵呵
- 事务使用分析经验总结
- 使用代码分析工具SOOT经验总结
- 做事务的经验总结
- 一个典型的事务使用错误分析
- 大数据分析经验总结
- 事务分析
- 经验总结55--spring开启事务回滚
- JfreeChart使用经验总结(分析了使用中碰到的一些常见问题)
- 水晶报表使用经验总结
- JTree使用经验总结
- JTree使用经验总结
- JTree使用经验总结
- swng-JTree使用经验总结
- VNC 使用经验总结
- JTree使用经验总结 - [ ] - [ ]
- JTree使用经验总结
- UrlRewriter 使用经验总结
- JTree使用经验总结
- PostgreSQL9.0 HA 双机热备配置
- linq to sql 之 增删改
- showModalDialog详解
- 数据库中的pureXML优点介绍
- 实现XML和Web服务时要避免的三种常见错误
- 事务使用分析经验总结
- 第01章 获得帮助
- 平板电脑:机会还是陷阱?
- 你所不知道的一些网站推广有效方法 站长须知
- 关于在MFC中调用AfxMessageBox、CWnd::MessageBox与::MessageBox的区别
- linq to sql 之 预备知识
- 移动流媒体技术及其应用发展方向
- 10.5XTB独家汇评:欧元中期涨势受阻
- 如何获取存储过程或触发器等中的print的字符串