Springboot有一致的事务模型
JDBC/Hibernate/myBatis
DataSource/JTA
事务抽象的核心接口
PlatformTransactionManager
DataSourceTransationManager
HibernateTransactionManager
JtaTransactionManager
TransactionDefinition
Propagation //传播性
Isolation //隔离性
Timeout //超时
Read-only status //是否只读
传播性 | 值 | 描述 |
PROPAGATION_REQUIRED | 0 | 当前有事务用当前的,没有就用新的 |
PROPAGATION_SUPPORTS | 1 | 事务可有可无,不是必须的 |
PROPAGATION_MANDATORY | 2 | 当前一定要有事务,不然就抛异常 |
PROPAGATION_REQUIRES_NEW | 3 | 无论是否有事务都起个新事务 |
PROPAGATION_NOT_SUPPORTED | 4 | 不支持事务,按非事务方式运行 |
PROPAGATION_NEVER | 5 | 不支持事务,如果有事务则抛异常 |
PROPAGATION_NESTED | 6 | 当前有事务就在当前是事务里再起一个事务 |
隔离性 | 值 | 脏读 | 不可重复读 | 幻读 |
ISOLATION_READ_UNCOMMITTER | 1 | T | T | T |
ISOLATION_READ_COMMITTED | 2 | F | T | T |
ISOLATION_REPEATABLE_READ | 3 | F | F | T |
ISOLATION_SERIALIZABLE | 4 | F | F | F |
编程式事务
TransactionTemplate
TransactionCallback
TransactionCallbackWithoutResult
PlatformTransactionManager
可以传入TransactionDefinition进行定义
通过编程式事务编写
package com.example.ribi;
import com.example.ribi.example.User;
import com.example.ribi.mapper.UserRepository;
import com.example.ribi.service.UserServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SpringBootApplication
@EnableCaching(proxyTargetClass = true)
@EnableTransactionManagement
@Slf4j
public class RibiApplication implements ApplicationRunner {
public static void main(String[] args) {
SpringApplication.run(RibiApplication.class, args);
}
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private TransactionTemplate transactionTemplate;
@Override
public void run(ApplicationArguments args) throws Exception{
log.info("0s count is {}",getCount()); //0s 一开始表里有的记录
jdbcTemplate.execute("insert into user values (10,'aaa','bbb')");
log.info("1s count is {}",getCount()); //1s 插入一条记录后
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
jdbcTemplate.execute("insert into user values (11,'aaa','bbb')");
log.info("2s count is {}",getCount()); //2s 开启事务设置回滚,插入一条记录再查询
status.setRollbackOnly();
}
});
log.info("3s count is {}",getCount()); //3s 查询事务回滚后的表记录数
}
public Long getCount(){
return (Long)jdbcTemplate.queryForList("select count(1) as CNT from user").get(0).get("CNT");
}
}
运行结果
2019-05-21 17:57:24.745 INFO 48768 --- [main] com.example.ribi.RibiApplication : 0s count is 4 // 一开始4条
2019-05-21 17:57:24.786 INFO 48768 --- [main] com.example.ribi.RibiApplication : 1s count is 5 // 插入一条后变5条
2019-05-21 17:57:24.805 INFO 48768 --- [main] com.example.ribi.RibiApplication : 2s count is 6 // 开启事务再插入一条查询变成6条 然后再回滚
2019-05-21 17:57:24.820 INFO 48768 --- [main] com.example.ribi.RibiApplication : 3s count is 5 // 回滚后变成5条
注解:
Application类添加
@EnableTransactionManagement
注解在方法头上添加
@Transactional
-- 部分摘自 极客时间 玩转Spring全家桶