结论:
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();
}
}