测试代码如下:
@SneakyThrows
public JsonResult createTable(String tableName,String dsId) {
if (StringUtils.isEmpty(dsId)) {
dsId = "1664472893795082241";
}
var ds = DruidUtils.getDataSource(dsId);
var template = new JdbcTemplate(ds);
//手动事务
var txManager=new DataSourceTransactionManager(ds);
DefaultTransactionDefinition transDef = new DefaultTransactionDefinition(); // 定义事务属性
transDef.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRED); // 设置传播行为属性
TransactionStatus status = txManager.getTransaction(transDef); // 获得事务状态
try {
TableModel t = new TableModel(tableName);
t.comment("测试创建的表");
t.column("id").VARCHAR(64).pkey().comment("主键");
t.column("name").VARCHAR(50).comment("姓名");
t.column("age").INTEGER().comment("年龄");
t.column("create_time").TIMESTAMP().comment("创建时间");
t.column("create_by").VARCHAR(64).comment("创建人");
Dialect dialect = Dialect.guessDialect(ds);
String[] ddlArray = dialect.toDropAndCreateDDL(t);
for (String ddl : ddlArray) {
template.execute(ddl);
}
String now = DateUtils.getTime();
String sql = "insert into " + tableName + " (id,name,age,create_time) values('101','李明',18,'" + now + "')";
template.execute(sql);
int j=1/0;
sql = "insert into " + tableName + " (id,name,age,create_time) values('102','李明2',38,'" + now + "')";
template.execute(sql);
sql = "select * from " + tableName;
JsonResult result = JsonResult.getSuccessResult("common.handleSuccess");
var data = template.queryForList(sql);
result.setData(data);
txManager.commit(status);// 提交
return result;
} catch (Exception e) {
txManager.rollback(status);// 回滚
return JsonResult.Fail(e.getMessage());
}
}
主要就是通过创建DataSourceTransactionManager
实例来管理事务,因为不确定是哪个数据源实例,所以不方便用@Transactional
注解。测试了MySQL
和PostgreSQL
两种数据库,如果只是两条insert
语句中间加一个异常,两种数据库都是可以正常回滚的。如果前面增加了删除表和创建表的SQL语句,PostgreSQL
表现正常,MySQL
的原来表中的数据却丢失了。看来MySQL
的DDL语句在事务中有时无法正常回滚,之前用Seata
的时候也遇到过,后来基本放弃Seata
了。