结论:

1. Spring事务不要用@Transaction(PS:如果用的话最好加到service层的方法上面而不要加到dao层、Controller层),会有一些情况导致事务回滚失败。

2. 最好使用代码来实现事务管理

3. 不要在事务里面执行RPC、HTTP请求等操作,避免由于网络抖动导致出现耗时事务的问题,耗时事务会长时间锁数据库.

   如果避免不了那么这就是一个分布式事务的问题了。

代码实现事务:

创建DataSource,使用阿里的德鲁伊

DruidDataSource dataSource = new DruidDataSource();

dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl(mysqlSettingParam.getUrl());
dataSource.setUsername(mysqlSettingParam.getUsername());
dataSource.setPassword(mysqlSettingParam.getPassword());
dataSource.setInitialSize(mysqlSettingParam.getInitialSize());
dataSource.setMaxActive(mysqlSettingParam.getMaxActive());
dataSource.setMinIdle(mysqlSettingParam.getMinIdle());
dataSource.setMaxWait(mysqlSettingParam.getMaxWait());
dataSource.setTestWhileIdle(mysqlSettingParam.getTestWhileIdle());
dataSource.setValidationQuery(mysqlSettingParam.getValidQuery());

创建事务管理器

import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Date;
import java.util.List;
    //定义事务管理器
    private PlatformTransactionManager txManager = null;

    @Autowired
    @Qualifier("DBMasterConfig.DataSource")
    DataSource dataSource;

    @Test
    public void insertChannel() throws Exception {
         AdChannelInfo adChannelInfo = new AdChannelInfo();
         adChannelInfo.setName("yangzhongyu");
         adChannelInfo.setChargePerson("yzy");
         adChannelInfo.setDesc("test");
         adChannelInfo.setCreatedAt(new Date());
         adChannelInfo.setUpatedAt(new Date());


        System.out.println("datasource="+dataSource);
        txManager = new DataSourceTransactionManager(dataSource);

        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
      //定义事务的隔离级别
       def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
  //定义事务的传播级别
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        //事务状态类,通过PlatformTransactionManager的getTransaction方法根据事务定义获取;获取事务状态后,Spring根据传播行为来决定如何开启事务
        TransactionStatus status = txManager.getTransaction(def);

        try {
            //操作数据库
            adChannelService.insert(adChannelInfo);

            //故意制造异常
            int i = 1/0;

            txManager.commit(status);  //提交status中绑定的事务,必须放在最后
        } catch (RuntimeException e) {
            txManager.rollback(status);  //回滚
            e.printStackTrace();
        }

    }

事务的实现原理(ThreadLocal)

 

10-16 19:50