最近遇到的一个比较诡异的问题,貌似各种配置都正确了,事务不起效。
首先resin服务器的配置文件连接数据库的配置如下:
<database> <jndi-name>jdbc/bbs7_app</jndi-name> <driver> <type>com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</type> <url>jdbc:mysql://192.168.74.5:3310/bbs7_pc_app?useUnicode=true&characterEncoding=GBK</url> <user>root</user> <password>root</password> </driver> <prepared-statement-cache-size>30</prepared-statement-cache-size> <max-connections>30</max-connections> <max-idle-time>120s</max-idle-time> </database>
spring的配置文件配置了注解开启:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <context:component-scan base-package="cn.pconline.bbs7"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> <tx:annotation-driven transaction-manager="transactionManager"/>
要加事务的public方法也已经加上了注解(注解只对public方法有效)
@Transactional public int updateTopicAndGetFloor(User user, Topic topic, Date now) { int floor = 0; if (!topic.isNoUp()) { topic.setLastPostAt(now); } topic.setLastPosterId(user.getUid()); StringBuilder sql = new StringBuilder("UPDATE ").append(TABLE_NAME).append( " SET replyCount=replyCount + 1, lastPosterId=?").append( ", lastPostAt=?, updateAt=?, floor=floor + 1 WHERE tid=?"); int result = topicXdb.getJdbcTemplate(topic.getFid()).update(topicXdb.xsql(topic.getFid(), sql.toString()), topic.getLastPosterId(), topic.getLastPostAt(), new Date(), topic.getTid()); if (result > 0) { removeFromCache(topic); // throw new RuntimeException("测试事务异常"); floor = getFloorFromDB(topic); } return floor; }
但是,手动测试让方法抛出一个RuntimeException的时候,数据没有回滚。
排除了半天,发现mysql的事务是默认提交的,把mysql的全局事务默认提交关闭后(如何设置事务关闭,参考这里:http://breezylee.iteye.com/admin/blogs/2052861),用root权限的用户登录,还是无效(mysql的bug,root用户事务默认提交),于是,换成其它一般权限的用户连接,发现还是不行(此时一般用户的事务,不是默认提交了)。
听一个牛人同事说,mysql的驱动com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource,不支持事务的,于是换成了com.mysql.jdbc.Driver,所以,数据源驱动配置改为如下:
<database> <jndi-name>jdbc/bbs7_app</jndi-name> <driver> <type>com.mysql.jdbc.Driver</type> <url>jdbc:mysql://192.168.74.5:3310/bbs7_pc_app?useUnicode=true&characterEncoding=GBK</url> <user>bbs7_pc_app</user> <password>bbs7_pc_app</password> </driver> <prepared-statement-cache-size>30</prepared-statement-cache-size> <max-connections>30</max-connections> <max-idle-time>120s</max-idle-time> </database>
改成这样之后,方法就有了事务控制了,抛异常之后数据可以正常回滚。
更正下,com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource这个驱动并不是不支持事务,上面的实验证明,貌似和spring的 jdbcTemplate操作、声明式事务@Transactional有点冲突。如果改用纯的jdbc操作,这个驱动还是支持事务的。
Connection conn = dataSource.getConnection();这样每次都是拿到一个新的连接,事务只在同一个连接里面有效,如果是多个连接,就是分布式事务,要换另一些解决方案。参考这里:
http://www.iteye.com/problems/89655
----------------------2014.8.8------------------
在这个环境下:
(1)mysql关闭自动提交
(2)程序没有加事务控制
(3)mysql的驱动用 com.mysql.jdbc.Driver
(4)用非root权限的普通权限的用户连接mysql
用spring的批量更新方法:jdbcTemplate.batchUpdate(sql.toString(), batch),
方法是执行成功了,但数据库没有更新到,就是说事务没有提交成功,如果执行完上面的batchUpdate后再手动commit,事务是可以提交成功的。
同样的环境,如果把驱动换成 com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource这个之后,不用手动commit,事务也可以提交成功。
具体原因不明,貌似是com.mysql.jdbc.Driver这个驱动不支持批量更新的事务。
相关推荐
Spring3事务管理——使用@Transactional 注解.rar
主要介绍了Java注解@Transactional事务类内调用不生效问题及解决办法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
本代码使用H2内存数据库演示spring事务使用,包括编程式事务,声明式事务@Transactional使用,自定义事务事务注解实现自定义事务管理器
我們使用Spring Framework裡,在Service 的 Method 給予@Transactional 系統就會去管理transaction,我們是在哪裡做了甚麼設定嗎? 為什麼下的這個Annotation成功會commit失敗會rollback呢? Transaction 管理做了...
Spring源码学习十二:@Transactional是如何工作的1
在本篇文章里小编给大家整理了关于Spring声明式事务@Transactional详解内容,需要的朋友们可以参考下。
主要介绍了Spring @Transactional工作原理详解,具有一定借鉴价值,需要的朋友可以参考下。
今天小编就为大家分享一篇关于springboot中事务管理@Transactional的注意事项与使用场景,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
spring事务管理注解jar,spring-tx-3.2.4.RELEASE.jar,导入项目即可
@Transactional实现原理.txt
声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,
Spring中的@Transactional事物回滚实例源码
主要介绍了深入学习Spring Boot排查 @Transactional 引起的 NullPointerException问题,需要的朋友可以参考下
a、b方法都可以有不同的传播级别或者不加事务注解(none): required(rd), required_new(rn), never(nr), supports(ss), not_supoort(ns), mandatory(mt), nested(ne) a和b方法都可能抛异常,对于b方法抛出的异常,a...
Spring中@Transactional事务回滚(含实例详细讲解,附源码)Java开发Java经验技巧共8页.pdf.zip
本篇文章主要介绍了浅谈Spring中@Transactional事务回滚及示例(附源码),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
主要介绍了Spring @Transactional注解失效解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
今天我们来探讨一个有意思的spring源码问题,也是一个学生告诉了我现象我从源码里面找到了这个有意思的问题。 首先我们看service层的代码案例,如下: @Service("transationServiceImpl") public class ...
主要介绍了spring的@Transactional注解用法解读,具有一定借鉴价值,需要的朋友可以参考下