spring 事务注意事项 -- 事务注解一定写到service最外层

事务采用的是注解方式。

持久层用的是MyBatis,简单配置如下:

 
id="mysqlDataSource" class="com.alibaba.druid.pool.DruidDataSource"  destroy-method="close">
    value="dataSource"/>
    
    name="url" value="${mysql.database.url}"/>
    name="username" value="${mysql.database.user}"/>
    name="password" value="${mysql.database.password}"/>

    
    name="initialSize" value="5"/>
    name="minIdle" value="${mysql.database.minIdle}"/>
    name="maxActive" value="${mysql.database.maxActive}"/>

    
    name="maxWait" value="60000"/>

    
    name="timeBetweenEvictionRunsMillis" value="60000"/>

    
    name="minEvictableIdleTimeMillis" value="300000"/>

    name="validationQuery" value="SELECT 1 FROM DUAL" />
    name="testWhileIdle" value="true"/>
    name="testOnBorrow" value="false"/>
    name="testOnReturn" value="false"/>

    
    name="filters" value="stat"/>

id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    name="dataSource" ref="mysqlDataSource"/>
    name="typeAliasesPackage" value="com.xxxxx.model"/>
    name="configLocation" value="classpath:/conf/mybatis/mybatis-config.xml"/>
    
    name="mapperLocations">
        
            classpath:/mappers/*.xml
        
    




class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    name="basePackage" value="com.xxxxx.dao"/>
 
   id="txMysqlManager"  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       name="dataSource" ref="mysqlDataSource" />
   
  
 
 
<tx:annotation-driven transaction-manager="txMysqlManager" proxy-target-class="true" order="50"/>


controller代码如下:

@RequestMapping(value="/testTransaction", method={RequestMethod.GET, RequestMethod.POST})
public  void  testTransaction() {
   try {
      ybsTrainingService.commitTransactionBase();
   } catch (Exception e) {

      logger.info("测试内容失败", e);

   }
}
servce代码如下:

@Transactional(value = "txMysqlManager", rollbackFor = Exception.class)
public void commitTransactionBase() {
    commitTransaction();
}
private void commitTransaction() {
    TrainingState trainingState = new TrainingState();
    trainingState.setTrainingId(220);
trainingState.setTrainingState( 1) ; //数据库上是3 trainingMapper.updateTrainingState(ybsTrainingState) ; CourseState ybsCourseState = new CourseState() ; courseState.setCourseState( 1) ; //数据库上是2 courseState.setId( 9348172) ; courseMapper.updateCourseState(ybsCourseState) ; //如下两行是异常测试 ,会报空指针异常
    ybsCourseState = null;
    ybsCourseState.setCourseState(1);
}

注意:如果将 “@Transactional(value ="txMysqlManager", rollbackFor = Exception.class)” 放到子方法commitTransaction()上边,如下,则事务不会起作用。

public void commitTransactionBase() {
    commitTransaction();
}
@Transactional(value = "txMysqlManager", rollbackFor = Exception.class)
private void commitTransaction() {   
    TrainingState trainingState = new TrainingState();
    trainingState.setTrainingId(220);
trainingState.setTrainingState( 1) ; //数据库上是3
    trainingMapper.updateTrainingState(ybsTrainingState);

    CourseState ybsCourseState = new CourseState();
    courseState.setCourseState(1);       //数据库上是2  
    courseState.setId(9348172);    
    courseMapper.updateCourseState(ybsCourseState);   

    //如下两行是异常测试 ,会报空指针异常
    ybsCourseState = null;
    ybsCourseState.setCourseState(1);
}

补充,最外层service方法,在这里边是commitTransactionBase() 方法,就是被controller直接调用的。所以肯定是public 修饰,如果是私有private修饰 ,则事务也不会生效,当然正常情况下,controller也不会调用到其他类的private方法。








你可能感兴趣的:(Spring)