public interface PlatformTransactionManager { void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException; TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException; } public interface TransactionDefinition { int getPropagationBehavior(); int getIsolationLevel(); int getTimeout(); boolean isReadOnly(); }
传播性 | 值 | 描述 | 备注 |
---|---|---|---|
PROPAGATION_REQUIRED | 0 | 当前事务有就用当前的,没有就用新的 | 默认 |
PROPAGATION_SUPPORTS | 1 | 事务可有可无,非必须 | |
PROPAGATION_MANDATORY | 2 | 当前一定要有事务,否则就抛异常 | |
PROPAGATION_REQUIRES_NEW | 3 | 无论是否有事务,都另起一个新的事务 | 会把旧事务挂起 |
PROPAGATION_NOT_SUPPORTED | 4 | 不支持事务,按非事务方式运行 | |
PROPAGATION_NEVER | 5 | 不支持事务,如果有事务就抛出异常 | |
PROPAGATION_NESTED | 6 | 当前有事务就在当前事务再起一个事务 | 1. 里面的事务拥有独立的属性,如回滚状态 2. 里面的事务回滚并不会影响外面的事务 |
隔离性 | 值 | 脏读 | 不可重复读 | 幻读 | 备注 |
---|---|---|---|---|---|
ISOLATION_DEFAULT | -1 | 取决于数据库配置 | |||
ISOLATION_READ_UNCOMMITTED | 1 | Y | Y | Y | |
ISOLATION_READ_COMMITTED | 2 | Y | Y | ||
ISOLATION_REPEATABLE_READ | 4 | Y | |||
ISOLATION_SERIALIZABLE | 8 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
CREATE TABLE PERSON ( ID BIGINT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(255) );
INSERT INTO PERSON (ID, NAME) VALUES ('1', 'zhongmingmao');
@Slf4j @SpringBootApplication public class ProgrammaticTransactionApplication implements CommandLineRunner { @Autowired private JdbcTemplate jdbcTemplate; @Autowired private TransactionTemplate transactionTemplate; public static void main(String[] args) { SpringApplication.run(ProgrammaticTransactionApplication.class, args); } @Override public void run(String... args) throws Exception { log.info("COUNT BEFORE TRANSACTION : {}", getCount()); transactionTemplate.execute(status -> { jdbcTemplate.update("INSERT INTO PERSON (NAME) VALUES ('A')"); log.info("COUNT IN TRANSACTION : {}", getCount()); status.setRollbackOnly(); return null; }); log.info("COUNT AFTER TRANSACTION : {}", getCount()); // 输出 // COUNT BEFORE TRANSACTION : 1 // COUNT IN TRANSACTION : 2 // COUNT AFTER TRANSACTION : 1 } private long getCount() { return jdbcTemplate.queryForObject("SELECT COUNT(*) FROM PERSON", Long.class); } }
public class TransactionTemplate extends DefaultTransactionDefinition implements TransactionOperations, InitializingBean{ } public class DefaultTransactionDefinition implements TransactionDefinition, Serializable { private int propagationBehavior = PROPAGATION_REQUIRED; private int isolationLevel = ISOLATION_DEFAULT; // -1 private int timeout = TIMEOUT_DEFAULT; // -1 private boolean readOnly = false; }
由于@EnableTransactionManagement的mode默认值为 PROXY ,PROXY对应的是 JDK动态代理 (基于 接口 )
public interface PersonService { void insert(); void insertThenRollback(); void invokeInsertThenRollback(); }
@Component public class PersonServiceImpl implements PersonService { @Autowired private JdbcTemplate jdbcTemplate; @Override @Transactional public void insert() { jdbcTemplate.update("INSERT INTO PERSON (NAME) VALUES ('A')"); } @Override @Transactional(rollbackFor = UnexpectedRollbackException.class) public void insertThenRollback() { jdbcTemplate.update("INSERT INTO PERSON (NAME) VALUES ('A')"); throw new UnexpectedRollbackException("Just For Test"); } @Override public void invokeInsertThenRollback() { // 方法的内部调用,没有走到增强的代理类上,因此也没有事务支持(实际是使用了数据库的隐式事务,自动提交) // 不会回滚!! insertThenRollback(); } }
@Slf4j @SpringBootApplication public class DeclarativeTransactionApplication implements CommandLineRunner { @Autowired private JdbcTemplate jdbcTemplate; @Autowired private PersonService personService; public static void main(String[] args) { SpringApplication.run(DeclarativeTransactionApplication.class, args); } @Override public void run(String... args) throws Exception { personService.insert(); log.info("insert, count : {}", getCount()); try { personService.insertThenRollback(); } catch (Throwable throwable) { log.info("insertThenRollback, count : {}", getCount()); } try { personService.invokeInsertThenRollback(); } catch (Throwable throwable) { log.info("invokeInsertThenRollback, count : {}", getCount()); } // 输出 // insert, count : 2 // insertThenRollback, count : 2 // invokeInsertThenRollback, count : 3 } private long getCount() { return jdbcTemplate.queryForObject("SELECT COUNT(*) FROM PERSON", Long.class); } }