文章目录
- Spring事务
- 使用Spring框架对Mybatis整合
- 事务的核心接口
- PlatformTransactionManager平台事务管理器
- TransactionStatus事务状态
- TransactionDefinition事务定义
- 事务的传播行为
- TransactionTemplate
- Transactional注解
Spring事务
使用Spring框架对Mybatis整合
上图中:绿色是手动注册的组件,黄色的是MapperScannerConfigure注册的组件
- 引入依赖
<!--Spring整合Mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.15.RELEASE</version>
</dependency>
<!--druid依赖-->
<!--可以监控程序的运行-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.11</version>
</dependency>
- 组件注册
@Configuration
@ComponentScan("com.coo1heisenberg.demo2")
public class AppConfiguration {
// @Bean
// public SqlSessionFactory sqlSessionFactory() {
//
// try {
// SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
// .build(Resources.getResourceAsStream("mybatis.xml"));
// return sqlSessionFactory;
// } catch (IOException e) {
// e.printStackTrace();
// }
// return null;
// }
/**
* mybatis-spring这个依赖提供了一个类,能够注册sqlSessionFactory组件
*
* sqlSessionFactoryBean implements FactoryBean<sqlSessionFactory>
*/
@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/coo1heisenberg?useSSL=false&characterEncoding=utf8");
dataSource.setUsername("root");
dataSource.setPassword("123456");
return dataSource;
}
@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {
MapperScannerConfigurer configurer = new MapperScannerConfigurer();
// 使用set方法提供一些信息
// 就会根据这些信息向mapper中注册组件
configurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
// sqlSessionFactory = applicationContext.getBean(beanName);
configurer.setBasePackage("com.coo1heisenberg.demo2.mapper");
return configurer;
}
}
- 在Service中可以直接注册Mapper
@Service
public class AccountServiceImpl implements AccountService {
// @Autowired
// SqlSessionFactory sqlSessionFactory;
@Autowired
AccountMapper accountMapper;
@Override
public int transfer(Integer fromId, Integer destId, Double money) {
// SqlSession sqlSession = sqlSessionFactory.openSession(true);
// AccountMapper mapper = sqlSession.getMapper(AccountMapper.class);
Double fromMoney = accountMapper.selectByPrimaryKey(fromId) - money;
Double destMoney = accountMapper.selectByPrimaryKey(destId) + money;
accountMapper.upDate(fromId, fromMoney);
int i = 1
accountMapper.upDate(destId, destMoney);
return 0;
}
}
- 测试文件
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfiguration.class)
public class MybatisSpringTest {
@Autowired
AccountService accountService;
@Test
public void test() {
accountService.transfer(1, 2, 100.0);
}
}
总结:Spring在Mybatis执行mapper的方法之后会立刻提交事务,而有时需要将多个方法放到一个事务里。
事务的核心接口
- PlatformTransactionManager 平台事务管理器
- TransactionStatus 事务状态
- TransactionDefinition 事务定义
PlatformTransactionManager平台事务管理器
- 平台事务管理器,Spring要管理事务,必须使用事务管理器
- 有多种实现,通过实现此接口,Spring可以管理任何实现了这些接口的事务
- 常见的事务管理器的实现:
-
DataSourceTransactionManager
,jdbc开发时事务管理器,使用JdbcTemplate
、MyBatis(SSM)
-
HibernateTransactionManager
,Hibernate开发时事务管理器,整合Hibernate(SSH)
-
public interface PlatformTransactionManager extends TransactionManager {
// 开启事务
TransactionStatus getTransaction(@Nullable TransactionDefinition var1)
throws TransactionException;
// 提交事务
void commit(TransactionStatus var1) throws TransactionException;
// 回滚事务
void rollback(TransactionStatus var1) throws TransactionException;
}
TransactionStatus事务状态
- 获取事务的状态(回滚点、是否完成、是否新事务、是否回滚)属性,是一个过程值
- 这个一般不需要关注
public interface TransactionStatus extends TransactionExecution
, SavepointManager, Flushable {
// 是否有保存点
boolean hasSavepoint();
//
void flush();
}
TransactionDefinition事务定义
- 定义事务的名称、隔离级别、传播行为、超时时间长短、只读属性等
public interface TransactionDefinition {
// 定义了一些成员变量
int PROPAGATION_REQUIRED = 0;
int PROPAGATION_SUPPORTS = 1;
int PROPAGATION_MANDATORY = 2;
int PROPAGATION_REQUIRES_NEW = 3;
int PROPAGATION_NOT_SUPPORTED = 4;
int PROPAGATION_NEVER = 5;
int PROPAGATION_NESTED = 6;
int ISOLATION_DEFAULT = -1;
int ISOLATION_READ_UNCOMMITTED = 1;
int ISOLATION_READ_COMMITTED = 2;
int ISOLATION_REPEATABLE_READ = 4;
int ISOLATION_SERIALIZABLE = 8;
int TIMEOUT_DEFAULT = -1;
// 下面是提供默认值和对应的方法
// jdk1.8之后才提供的default
default int getPropagationBehavior() {
return 0;
}
default int getIsolationLevel() {
return -1;
}
default int getTimeout() {
return -1;
}
default boolean isReadOnly() {
return false;
}
@Nullable
default String getName() {
return null;
}
static TransactionDefinition withDefaults() {
return StaticTransactionDefinition.INSTANCE;
}
}
事务的传播行为
- 指多个方法之间如何来共享事务:发生异常的情况,谁提交谁回滚
-
REQUIRED
(默认的事务传播行为)- 一荣俱荣,同生共死
- 要么一起提交,要么一起回滚
- 一荣俱荣,同生共死
-
REQUIRES_NEW
- 自私型
- 部不会影响内部,内部会影响外围
- 内部的方法更重要
- 自私型
-
NESTED
- 无私型
- 外围会影响内部,内部不会影响外围
- 外部的方法更重要
- 无私型
- 其他传播行为
传播行为 | 描述 |
---|---|
PROPAGATION_SUPPORTS | 支持当前事务,假设当前没有事务,就以非事务方式运行 |
PROPAGATION_MANDATORY | 支持当前事务,假设当前没有事务,就抛出异常 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式运行操作。假设当前存在事务,就把当前事务挂起 |
PROPAGATION_NEVER | 以非事务方式运行,假设当前存在事务,则抛出异常 |
eg:
-
config
目录下的AppConfiguration
注册组件
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
-
service
目录下
@Autowired
PlatformTransactionManager platformTransactionManager;
@Override
public int transfer(Integer fromId, Integer destId, Double money) {
Double fromMoney = accountMapper.selectByPrimaryKey(fromId) - money;
Double destMoney = accountMapper.selectByPrimaryKey(destId) + money;
// 开启事务
TransactionStatus status = platformTransactionManager
.getTransaction(TransactionDefinition.withDefaults());
try {
accountMapper.upDate(fromId, fromMoney);
int i = 1 / 0;
accountMapper.upDate(destId, destMoney);
}catch (Exception e) {
// 事务的回滚
platformTransactionManager.rollback(status);
e.printStackTrace();
}
// 提交事务并关闭
platformTransactionManager.commit(status);
return 0;
}
TransactionTemplate
- 事务的模板,采用事务模板提供的方法来使用事务
- 对上面事务的传播行为做一系列的封装
- 下图的绿色是需要写的业务代码
eg:
-
config
目录下的AppConfiguration
注册组件
@Bean
public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
TransactionTemplate transactionTemplate = new TransactionTemplate();
transactionTemplate.setTransactionManager(transactionManager);
return transactionTemplate;
}
-
service
目录下
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
AccountMapper accountMapper;
@Autowired
TransactionTemplate transactionTemplate;
@Override
public int transfer(Integer fromId, Integer destId, Double money) {
Double fromMoney = accountMapper.selectByPrimaryKey(fromId) - money;
Double destMoney = accountMapper.selectByPrimaryKey(destId) + money;
TransactionCallback<Object> transactionCallback = new TransactionCallback<Object>() {
@Override
public Object doInTransaction(TransactionStatus transactionStatus) {
accountMapper.upDate(fromId, fromMoney);
int i = 1 / 0;
accountMapper.upDate(destId, destMoney);
return null;
}
};
transactionTemplate.execute(transactionCallback);
return 0;
}
}
Transactional注解
- 采用AOP的方式给容器的组件生成代理对象
-
@Transactional
注解的ElementType为TYPE和METHOD,意味着可以写在类上或方法上
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
@AliasFor("transactionManager")
String value() default "";
@AliasFor("value")
String transactionManager() default "";
Propagation propagation() default Propagation.REQUIRED;
Isolation isolation() default Isolation.DEFAULT;
int timeout() default -1;
boolean readOnly() default false;
Class<? extends Throwable>[] rollbackFor() default {};
String[] rollbackForClassName() default {};
Class<? extends Throwable>[] noRollbackFor() default {};
String[] noRollbackForClassName() default {};
}
-
使用注解
- 使用注解前,需要先打开事务的注解驱动
@Configuration @ComponentScan("com.coo1heisenberg.demo4") @EnableTransactionManagement public class AppConfiguration {}
-
直接使用
@Transactional
注解,可以使用注解提供的属性配置事务的TransactionDefinition
@Service // @Transactional(readOnly = true) // @Transactional(timeout = 4) public class AccountServiceImpl implements AccountService { @Autowired AccountMapper accountMapper; @Override @Transactional public int transfer(Integer fromId, Integer destId, Double money) { Double fromMoney = accountMapper.selectByPrimaryKey(fromId) - money; Double destMoney = accountMapper.selectByPrimaryKey(destId) + money; accountMapper.upDate(fromId, fromMoney); int i = 1 / 0; accountMapper.upDate(destId, destMoney); return 0; } }