Spring封装了事务管理的代码
事务的操作一般有三种:
- 打开事务
- 提交事务
- 回滚事务
Spring中管理事务的对象
因为在不同平台,操作事务的代码各不相同,spring提供了一个接口.
PlatfromTransactionManager接口
在开发中都是直接使用它的实现类,常用的实现类有如下:
- DataSourceTransactionManager 使用jdbc或者mybatis进行数据持久化时使用
- HiberanteTransactionManager ==使用hibernate进行数据持久化时使用==
TransactionDefinition
它是一个接口,是定义事务的信息对象,提供了如下常用的方法:
TransactionStatus
它是一个接口,提供了事务具体的执行状态,描述了某一个时间点上事务对象的状态信息。提供了如下常用的方法:
==注意:在spring中使用事务,最为核心的对象就是TransactionManager对象==
==记得在spring配置文件中必须配置TranscationManager==
Spring管理事务的属性介绍
- 事务的隔离级别
-
- 读未提交
-
- 读已提交
-
- 可重复读
-
- 串行化
- 是否只读
- true 只读
- false 可操作
- 事务的传播行为
保证同一个事务中
属性 | 含义 |
---|---|
PROPAGATION_REQUIRED | 支持当前事务,如果不存在 就新建一个(默认) |
PROPAGATION_SUPPORTS | 支持当前事务,如果不存在,就不使用事务 |
PROPAGATION_MANDATORY | 支持当前事务,如果不存在,抛出异常 |
保证没有在同一个事务中
属性 | 含义 |
---|---|
PROPAGATION_REQUIRES_NEW | 如果有事务存在,挂起当前事务,创建一个新的事务 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式运行,如果有事务存在,挂起当前事务 |
PROPAGATION_NEVER | 以非事务方式运行,如果有事务存在,抛出异常 |
PROPAGATION_NESTED | 如果当前事务存在,则嵌套事务执行 |
超过时间
以秒为单位进行设置。如果设置为-1(默认值),表示没有超时限制.
no-rollback-for:指定产生某个异常时,不回滚。产生其他异常时回滚。没有默认值,任何异常都回滚
rollback-for:指定产生某个异常时,回滚。产生其他异常时不回滚。没有默认值,任何异常都回滚
Spring管理事务方式
1. 编码式
步骤
- 将核心事务管理器配置到spring的容器中
//核心事务管理器是依赖于数据源的
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
复制代码
- 配置事务管理模板TransactionTemplate
<!-- 事务模板 -->
<bean name="Template" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
复制代码
- 将事务模板注入到Service中
<bean name="AccountService" class="madness.service.AccountServiceImpl">
<property name="dao" ref="AccountDao"></property>
<property name="template" ref="Template"></property>
</bean>
复制代码
- 在Service中调用模板
注意:在模板中,已经实现了开启事务,提交事务,回滚事务的方法.
public class AccountServiceImpl implements AccountService {
private AccountDao dao;
private TransactionTemplate template;
@Override
public void tranfer(Integer from, Integer to, String money) {
template.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
dao.takeMoney(from, money);
//int i = 100/0;
dao.saveMoney(to, money);
}
});
}
public void setDao(AccountDao dao) {
this.dao = dao;
}
public void setTemplate(TransactionTemplate template) {
this.template = template;
}
}
复制代码
2. xml配置
- 导包
- 导入约束
- spring压缩包中的schema文件夹中的tx文件夹
- 配置通知
<!-- config TransactionManagerAdvice -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="tranfer" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
</tx:attributes>
</tx:advice>
复制代码
- 注意:这里的tx:method中的name属性是根据我们的方法来找的.如果我们每次的方法名都不一样,每次都要进行配置.为了避免重复,我们可以将方法名规定好
- 将通知织入目标对象
<aop:config>
<aop:pointcut expression="execution( * madness.service.*ServiceImpl.*(..))" id="txPc"/>
<!--
配置切面:通知+切点
advice-ref:通知的名称
pointcut-ref:切点的名称
-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"/>
</aop:config>
复制代码
3. 注解配置
- 导包
- 导入约束
- 开始注解配置事务
<tx:annotation-driven/>
@EnableTransactionManagement注解:启用spring注解事务支持
复制代码
- 使用注解配置事务
@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,readOnly=false)
复制代码
- ==如果方法太多我们可以将注解配置在类上.==
@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,readOnly=false)
public class AccountServiceImpl implements AccountService {
复制代码
- ==如果其中有方法的注解配置不一样,我们可以在该方法上另外使用注解进行配置==
@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,readOnly=false)
public class AccountServiceImpl implements AccountService {
private AccountDao dao;
@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,readOnly=true)
public void tranfer(Integer from, Integer to, String money) {
dao.takeMoney(from, money);
//int i = 100/0;
dao.saveMoney(to, money);
}
public void setDao(AccountDao dao) {
this.dao = dao;
}
复制代码
4. 纯注解配置
不使用applicationContext.xml文件,使用配置类来达到纯注解配置spring
- 主配置类
@Configuration
@ComponentScan("com.itheima")
@Import(value = { DaoConfig.class, TransactionConfig.class })
@PropertySource("classpath:db.properties")
@EnableTransactionManagement
public class SpringConfig {
}
复制代码
- Dao配置类(数据源与jdbcTemplate模板)
public class DaoConfig {
@Value("${jdbc.driverClass}")
private String driverClass;
@Value("${jdbc.jdbcUrl}")
private String url;
@Value("${jdbc.user}")
private String user;
@Value("${jdbc.password}")
private String password;
@Bean("dataSource")
public DataSource getDataSource(){
ComboPooledDataSource ds = new ComboPooledDataSource();
try {
ds.setDriverClass(driverClass);
ds.setJdbcUrl(url);
ds.setUser(user);
ds.setPassword(password);
} catch (Exception e) {
e.printStackTrace();
}
return ds;
}
@Bean("jdbcTemplate")
public JdbcTemplate getJdbcTemplate(@Qualifier("dataSource") DataSource dataSource){
JdbcTemplate jt = new JdbcTemplate(dataSource);
return jt;
}
}
复制代码
- 事务管理器配置类
public class TransactionConfig {
@Bean("transactionManager")
public PlatformTransactionManager getTranscationManager(@Qualifier("dataSource") DataSource dataSource){
DataSourceTransactionManager dt = new DataSourceTransactionManager(dataSource);
return dt;
}
}
复制代码