设为首页 收藏本站
查看: 698|回复: 0

[经验分享] spring结合mysql事务注解@Transactional不起作用的问题

[复制链接]

尚未签到

发表于 2016-10-19 07:14:32 | 显示全部楼层 |阅读模式
  最近遇到的一个比较诡异的问题,貌似各种配置都正确了,事务不起效。
  首先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&amp;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.iyunv.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&amp;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.iyunv.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这个驱动不支持批量更新的事务。
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-288093-1-1.html 上篇帖子: MySQL的Replace into 与Insert into ..... on duplicate key update ...真正的不同之处 下篇帖子: MySQL 数据库镜像(复制) / 实时备份Zen Cart数据库 十一
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表