Home  >  Article  >  Database  >  spring结合mysql事务注解@Transactional不起作用的有关问题

spring结合mysql事务注解@Transactional不起作用的有关问题

WBOY
WBOYOriginal
2016-06-07 16:25:331509browse

spring结合mysql事务注解@Transactional不起作用的问题 最近遇到的一个比较诡异的问题,貌似各种配置都正确了,事务不起效。 首先resin服务器的配置文件连接数据库的配置如下: databasejndi-namejdbc/bbs7_app/jndi-namedrivertypecom.mysql.jdbc.jdbc2.opti

spring结合mysql事务注解@Transactional不起作用的问题

最近遇到的一个比较诡异的问题,貌似各种配置都正确了,事务不起效。

首先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的全局事务默认提交关闭后,用root权限的用户登录,还是无效(mysql的bug),于是,换成其它一般权限的用户连接,发现还是不行。

听一个牛人同事说,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

?

?

?

?

?

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn