spring声明式事务内部具体是通过AOP技术实现的:
Spring通过事务管理器管理事务,提供了统一的事务管理器接口,和针对各主流持久化平台的事务管理器的实现,在事务管理器的实现中将事务操作委托给具体的持久化平台
Spring声明式事务管理的开发步骤:
1.在配置类上加注解@EnableTransactionManagement启用注解式事务配置
2.在配置类上配置事务管理器,还要有具体的持久化平台,即数据源
3.在业务实现类上添加声明式事务注解@Transactional
下面所有的开发都基于上一篇整合jdbc基础之上
一. 开发配置类
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
@ComponentScan({"org.xupt.ygq.demo.dao","org.xupt.ygq.demo.service"})
//属性资源读取 ignoreResourceNotFound如果某个属性没找到忽略资源 不报错
@PropertySource(value = "classpath:application.properties",ignoreResourceNotFound = true)
@EnableTransactionManagement//启用注解式事务管理,该注解只能加在配置类上
public class MyConfig {
//数据源需要的四个参数,我们从属性中进行加载,属性的值我们存放在资源文件中
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
//数据源是第三方写的所以我们只能在配置类里面配置,自己写的就可以用@Component注解放入容器中
@Bean
public DataSource druidDataSource(){
//创建一个数据源
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driverClassName);
druidDataSource.setUrl(url);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
return druidDataSource;
}
@Bean
//配置针对已知数据源的事务管理器 PlatformTransactionManager事务管理器接口
//只要加了@Bean注解有参数自动去容器里面找,这个数据源也就是上面受spring管理的数据源
public PlatformTransactionManager txManager(DataSource ds){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(ds);
return transactionManager;
}
}
一个注解:
@EnableTranscationManagement:启用注解式事务管理,该注解只能加在配置类上
两个配置:
①:数据源的配置:通过@Bean注解让Spring进行管理
②:事务管理器的配置:构造方法传入数据源,不需要注解,创建事务管理器
二. 业务类实现上添加声明式注解@Transcational
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.xupt.ygq.demo.dao.MyDao;
import org.xupt.ygq.demo.dto.UserDto;
import org.xupt.ygq.demo.service.MyService;
@Service
//@Transactional//声明本组件所有的方法都是事务性的 这个注解也可以只放在方法上,只说明这个方法是事务性的
public class MyServiceImpl implements MyService {
@Autowired
private MyDao myDao;
@Override
//这个方法是事务性的 (rollbackFor = Exception.class所有异常都会滚,默认的是运行时异常回滚)
//propagation = Propagation.REQUIRED 默认的传播规则,被嵌套的事务融入大事务中
@Transactional(readOnly = false,rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
public void fn() {
UserDto userDto = new UserDto();
userDto.setU_id("A005");
userDto.setU_name("人5");
userDto.setU_pwd("000002");
myDao.insertOneUser(userDto);
//myDao.insertOneUser(userDto);
}
}
1.@Transcational:这个注解也能家在方法上,表示这个方法是事务性的
2.@Transcational有很多的属性,如果在类上使用该注解定义了属性,而方法上没有使用该注解定义相同的属性,则自动继承类上的注解定义的属性,如果方法上和类上都使用该注解定义了相同的属性,则以方法上的为准。
3@Transcational的readOnly属性:本方法是否只读,如果设置为只读,内部会针对只读事务做出优化
4.timeout属性:设置超时时间,如果超过一定时间,方法没有结束,自动回滚
5.rollbackFor属性:设置什么类型的异常回滚,默认是运行时异常回滚,上述设置是任何异常都会滚
6.norollbackFor属性
7.propagation(事务传播机制)属性;
①:Propagation.REQUIRED:被嵌套的事务融入大事务环境中,共用同一个事务(Spring默认的事务传播机制)
②:Propagation.REQUIRED_NEW:被嵌套的事务不融入大事务环境中,是一个独立的事务,相当于创建一个新事务(新开启的事务与原有的大事务环境无关,原有事务回滚,不影响新事务)
③:Propagation.NOT_SUPPORTED:不支持事务,如果处于被大事务环境包围中,直接报错
④:Propagation.SUPPORTED:支持事务,若处于大事务环境中,则融入事务,否则自身也不是事务。
8.@Transcational的isolation属性:设置隔离级别