带有myBatis的DataSourceTransactionManager回滚无法正常工作

时间:2015-07-08 04:35:51

标签: java spring ibatis spring-transactions

我正在尝试编写一个演示来了解spring事务。这是spring-config.xml中的配置:

<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close" scope="prototype">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost/test"/>
        <property name="username" value="root"/>
        <property name="password" value="#Bugsfor$"/>
   </bean>      
   <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
          <property name="dataSource" ref="dataSource" />
   </bean>


   <tx:advice id="txAdvice" transaction-manager="transactionManager">
          <tx:attributes>                     
                 <tx:method name="get*" read-only="true"/>
                 <tx:method name="*"/>
          </tx:attributes>
   </tx:advice>

   <aop:config>
          <aop:pointcut id="categoryDAOOperation" expression="execution(* com.ea.test.dao.CategoryDAO.*(..))"/>
          <aop:advisor advice-ref="txAdvice" pointcut-ref="categoryDAOOperation"/>
   </aop:config>

   <!-- define the SqlSessionFactory -->
   <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
          <property name="dataSource" ref="dataSource"/>
          <property name="mapperLocations">
                 <list>
                        <value>classpath:mapper/CategoryMapper.xml</value>
                 </list>
          </property>
   </bean>

   <bean id="categoryMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
          <property name="mapperInterface" value="com.ea.test.mapper.CategoryMapper"/>
          <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
   </bean>
   <bean id="categoryDAO" class="com.ea.test.dao.CategoryDAO">
          <property name="categoryMapper" ref="categoryMapper"/>
   </bean>

以下是CategoryDAO.java

public class CategoryDAO {
CategoryMapper categoryMapper;

public void setCategoryMapper(CategoryMapper categoryMapper) {
    this.categoryMapper = categoryMapper;
}


public CategoryDB get(int id) {
    logger.info("Start to get category for id: {}", id);
    CategoryDB retValue = categoryMapper.get(id);
    logger.info("Get category for id: {} successfully", id);
    return retValue;
}

public void save(CategoryDB categoryDB) {
    categoryMapper.save(categoryDB);
    throw  new UnsupportedOperationException("unsupported");

}

}

CategoryService.java

public class CategoryService {
public static void main(String[] args) throws Exception {
    ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {
            "spring-config.xml"
    });

    CategoryDAO categoryDAO = (CategoryDAO) context.getBean("categoryDAO");
    CategoryDB categoryDB = new CategoryDB();
    categoryDB.setId(1);
    categoryDB.setName("AAA");
    categoryDAO.save(categoryDB);

}
}

这是运行时的DEBUG日志

08/07/15 12:22:40:344: [main]: DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager  - Acquired Connection [ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@325dc1bc]]] for JDBC transaction
  08/07/15 12:22:40:348: [main]: DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager  - Switching JDBC Connection [ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@325dc1bc]]] to manual commit
  08/07/15 12:22:40:374: [main]: DEBUG org.mybatis.spring.SqlSessionUtils  - Creating a new SqlSession
  08/07/15 12:22:40:377: [main]: DEBUG org.mybatis.spring.SqlSessionUtils  - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@27589aa5]
  08/07/15 12:22:40:407: [main]: DEBUG org.springframework.jdbc.datasource.DataSourceUtils  - Fetching JDBC Connection from DataSource
  08/07/15 12:22:40:407: [main]: DEBUG org.springframework.jdbc.datasource.DataSourceUtils  - Registering transaction synchronization for JDBC Connection
  08/07/15 12:22:40:407: [main]: DEBUG org.mybatis.spring.transaction.SpringManagedTransaction  - JDBC Connection [ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@1d10e937]]] will be managed by Spring
  08/07/15 12:22:40:408: [main]: DEBUG com.ea.test.mapper.CategoryMapper.save  - ooo Using Connection [ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@1d10e937]]]
  08/07/15 12:22:40:416: [main]: DEBUG com.ea.test.mapper.CategoryMapper.save  - ==>  Preparing: insert into CATEGORY ( CATEGORY_ID, CATEGORY_NAME ) values ( ?, ? ) 
  08/07/15 12:22:40:456: [main]: DEBUG com.ea.test.mapper.CategoryMapper.save  - ==> Parameters: 1(Integer), AAA(String)
  08/07/15 12:22:40:492: [main]: DEBUG org.mybatis.spring.SqlSessionUtils  - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@27589aa5]
  08/07/15 12:22:40:493: [main]: DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager  - Initiating transaction rollback
  08/07/15 12:22:40:493: [main]: DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager  - Rolling back JDBC transaction on Connection [ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@325dc1bc]]]
  08/07/15 12:22:40:494: [main]: DEBUG org.mybatis.spring.SqlSessionUtils  - Transaction synchronization rolling back SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@27589aa5]
  08/07/15 12:22:40:494: [main]: DEBUG org.mybatis.spring.SqlSessionUtils  - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@27589aa5]
  08/07/15 12:22:40:494: [main]: DEBUG org.springframework.jdbc.datasource.DataSourceUtils  - Returning JDBC Connection to DataSource
  08/07/15 12:22:40:495: [main]: DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager  - Releasing JDBC Connection [ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@325dc1bc]]] after transaction
  08/07/15 12:22:40:495: [main]: DEBUG org.springframework.jdbc.datasource.DataSourceUtils  - Returning JDBC Connection to DataSource
Exception in thread "main" java.lang.UnsupportedOperationException: unsupported
at com.ea.test.dao.CategoryDAO.save(CategoryDAO.java:40)
at com.ea.test.dao.CategoryDAO$$FastClassByCGLIB$$c0f75c81.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
at com.ea.test.dao.CategoryDAO$$EnhancerByCGLIB$$4d1a773e.save(<generated>)
at com.ea.test.service.CategoryService.main(CategoryService.java:25)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

CategoryDAO抛出UnSupportedOperationExecption,所以我认为CatetegoryMapper.save会回滚。但事实并非如此。对于DataSource.defaultAutoCommit为真,CatetegoryMapper.save应该在抛出UnSupportedOperationExecption之前提交。然后我将D ataSource.defaultAutoCommit设置为false,但我发现CatetegoryMapper.save将永远不会提交,无论是否抛出UnSupportedOperationExecption。我不知道为什么。

我的配置文件中有什么问题,或者我对它有一些误解。非常感谢

1 个答案:

答案 0 :(得分:0)

我知道配置有什么问题。我只是犯了一个非常愚蠢的错误。我将dataSource的范围配置为prototypesqlSessionFactorytransactionManager中有两个不同的dataSource。然后我删除它工作的范围

<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost/test"/>
    <property name="username" value="root"/>
    <property name="password" value="#Bugsfor$"/>
</bean>