前言
提示:本次个人笔记,将记录spring中关于事务相关
一、事务的回顾
什么是事务:事务是指数据库中多个操作合并再一起执行的操作顺序
个人理解:就是将对数据库执行的、多个操作形成的、最终结果进行最终决断性处理。
事务的作用:
当数据库操作序列中的个别操作失败时,提供一种方式使数据库恢复到正常的状态
- (A原子性)保障数据库即使在异常情况下也能保持数据的一致性
- (C一致性)要么操作前状态,要么操作后状态
- (I隔离性)当出现并发访问数据库时可以保证数据之间不相互干扰
- (D) 以及事务的4种隔离级别
Spring事务的核心对象- platformTransactionManager——平台事务管理器
- TransactionDefinition
- TransactionSatus
二、事务管理
spring事务核心对象
1.PlantformTransactionManager:平台事物管理器实现类
- DataSourceTransactionManager 适用于Spring JDBC或MyBatis
- HibernateTransactionManager 适用于Hibernate3.0及以上版本
- JpaTransactionManager 使用于JPA
- JdoTransactionManager 适用于JDO
- JtaTransactionManager 使用于JTA
JPA(Java Persistence API)Java EE 标准之一,为POJO提供持久化标准规范,并规范了持久化开发的统一API,符合JPA规范的开发可以在不同的JPA框架下运行
JDO(Java Data Object )是Java对象持久化规范,用于存取某种数据库中的对象,并提供标准化API。与JDBC相比,JDBC仅针对关系数据库进行操作,JDO可以扩展到关系数据库、文件、XML、对象数据库(ODBMS)等,可移植性更强
JTA(Java Transaction API)Java EE 标准之一,允许应用程序执行分布式事务处理。与JDBC相比,JDBC事务则被限定在一个单一的数据库连接,而一个JTA事务可以有多个参与者,比如JDBC连接、JDO
都可以参与到一个JTA事务中
此接口定义了事物的基本操作
- 获取食物
TransactionStatus getTransaction(TransactionDefinition definition)
- 提交事务
void commit(TransactionStatus status)
- 回滚事务
void rollback(TransactionStatus status)
2.TransactionDefinition
此接口定义了事务的基本信息
- 获取事务定义名称
String getName()
- 获取事务的读写属性
boolean isReadOnly()
- 获取事务隔离级别
int getIsoLationlevel()
- 获取事务超时时间
int getTimeout()
- 获取食物传播行为特征
int getPropagationBehavior()
3.TranscactionStatus
此接口定义了事务在执行过程中某个时间点上的状态信息以及对应的状态操作
- 获取食物是否处于断开食物状态
boolean isNewTransaction()
- 获取事务是否处于已经完成状态
booolean isCompleted()
- 获取事务是否处于回滚状态
boolean isRollbackOnly()
- 刷新事务状态
void flush()
- 获取事务是否具有回滚存储点
boolean hasSavepoint()
- 设置事务处于回滚状态
void setRollbackOnly()
4.事务控制方式
- 编程式
- 声明式(XML)
- 声明式(注解)
4.1编程式事务
public void a(){
//创建事务管理器
DataSourceTransactionManager dstm = new DataSourceTransactionManager();
//为事务管理器设置与数据层相同的数据源
dstm.setDataSource(dataSource);
//创建事务定义对象
TransactionDefinition td = new DefaultTransactionDefinition();
//创建事务状态对象,用于控制事务执行
TransactionStatus ts = dstm.getTransaction(td);
/**
*此处为自定义的事务
*/
//提交事务
dstm.commit(ts);
}
4.2 使用AOP控制事务
将业务层的事务处理功能抽取出来制作成AOP通知,利用环绕通知运行期动态织入
public Object tx(ProceedingJoinPoint pjp)throws Throwable{
DataSourceTranmsactionManager dstm = new DataSourceTransactionManager();
dstm.setDataSource(dataSource);
TreansactionDefinition td = dstm.getTransaction(td);
Object ret pjp.proceed(pjp.getArgs());
dstm.commit(ts);
return ret;
}
配置AOP通知类,并注入dataSource
<bean id="txAdvice" class="com.包名.aop.TxAdvice">
<property name="dataSource" ref="dataSource"/>
</bean>
使用环绕通知将通知类织入到原始业务对象执行过程中
<aop:config>
<aop:pointcut id="pt" experession="execution(* *..transfer(..))"/>
<aop:aspect ref="txAdvice">
<aop:around method="tx" pointcut-ref="pt"/>
</aop:aspect>
</aop:config>
4.3声明事务(XML)
public Object tx(proceedingjionPoint pjp)throws Throwable{
DataSourceTransactionManager dstm =new DataSourceTransactionManager();
dstm.setDataSoutce(dataSource);
TransactionDefinition td = new DefaultTransactionDefinition();
transactionStatus ts = dstm.getTransaction(td);
Object ret = pjp.proceed(pjp.getArgs());
dstm.commit(ts);
return ret;
}
<bean id="txAdvice" class="com.包名.aop.TxAdvice">
<property name="dataSource" ref="dataSource"/>
</bean>
使用tx命名空间破欸之事务专属通知类
<aop:config>
<aop:pointcut id="pt" expression="execution(* *..*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
</aop:config>
4.4 aop:advice与aop:advisior区别
- aop:advice配置的通知类可以是普通java对象,不实现接口,也不使用继承关系
- aop:advisior配置的通知类必须实现通知接口
- MethodBeforeAdvice
- AfterReturningAdvice
- thorwsAdvice
4.5 tx配置——tx:advice
- 名称:tx:advice
- 类型:标签
- 归属:beans标签
- 作用:专用于声明事务通知
- 格式
<beans>
<tx:advice id="txAdvice" transaction-manager="txMagager">
</tx:advice>
</beans>
- 基本属性
- id:用于配置aop时指定通知的id
- transaction—manager:指定事务管理bean
4.6 tx配置——tx:attributes
- 名称:tx:attributes
- 类型:标签
- 归属:tx:advice标签
- 作用:定义通知属性
- 格式:
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
</tx:attributes>
</tx:advice>
4.7 tx配置—tx:method
- 名称:tx:method
- 类型:标签
- 归属:tx:attribute标签
- 作用:设置具体的事物特性
- 格式:
<tx:attributes>
<tx:methoud name="*" read-only="false"/>
<tx:method name="get*" read-only="true"/>
</tx:attributes>
注意:通常事物属性会配置多个,包含1个读写的全事物属性,1个只读的查询类事物属性
tx:method属性
<tx:method
name="*" 待添加的事务方法名表达式(支持*号通配符),例如get*、*...
read-only="false" 设置事务的读写属性,true为只读,falase为读写
timeout="-1" 设置事务超时时长,单位为秒
isolation="DEFAULT" 设置事务隔离级别,该隔离设定是基于Spring的设定,非数据库端
no-roollback-for="" 设置事务中不回滚的异常,多个异常间使用,分割
rollback-for="" 设置事务必回滚的异常,多个异常间使用,分割
propagation="gREQUIRED" 设置事务的传播行为
/>
5. 事务的传播行为
- 事务管理员
- 事务协调员
- 事务传播行为描述的是事务协调员对事物管理员所携带事物的处理态度
事物传播行为:
6. 声明式事务(注解)
6.1)@Transactional
- 名称:@Transactional
- 类型:方法注解,类注解,接口注解
- 位置:方法定义上方,类定义上方,接口定义上方
- 作用:设置当前类/接口中所有方法或具体方法开启事务,并指定相关事务属性
- 范例:
@Transactional(
readOnly = false,
timeout = -1,
isolation = Isolation.DEFAULT,
rollbackFor = {ArithmeticException.class,IOException.class},
noRollbackFor = {},
propagation = Propagation.REQUIRES_NEW
)
6.2)tx:annotation-driven
- 名称:tx:annotation-driven
- 类型:标签
- 归属:beans标签
- 作用:开启事务注解启动,并并指定对应的事务管理器
- 范例:
<tx:annotation-driven transaction-manager="txManager"/>
6.3)声明式事务(纯注解驱动)
- 名称:@EnableTransactionManagement
- 类型:类注解
- 位置:Spring注解配置类上方
- 作用:开启注解驱动,等同XML格式中的注解驱动
- 范例:
@Configuration
@ComponentScan("你的最小包含所有代码的包类似于:com.qqq")
@PropertySource("classpath:jdbc.properties")
@Import({JDBCConfig.class,MyBatisConfig,class,TransactionManagerConfig.class})
@EnableTransactionManagement
public class SpringConfig{}
public class TransactionManagerConfig{
@Bean
public PlatformTransactionManager getTransactionManager(@Autowired DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
}
三、模板对象
1.Spring模块对象
- TransactionTemplate
- JdbcTempalte
- RedisTemplate
- JmsTemplate
- HibernateTemplate
- RestTemplate
2.JdbcTemplate
提供标准的sql语句操作API
public void save(Account account){
String sql = "INSERT INTO account(name,money)values(?,?)";
jdbcTemplate.update(sql,account.getName(),account.getMoney());
}
3.NamedParameterJdbcTemplate
提供标准的具体sql语句操作API
public void save(Account account){
String sql = "INSERT INTO account(name,age)VALUES(:name,:age)";
Map pm = new HashMap();
pm.put("name",account.getName());
pm.put("age",account.getAge());
jdbcTemplate.update(sql,pm);
}
4.RedisTemplate
RedisTemplate对象结构
public void changeMoney(Integer id ,Double money){
redisTemplate.opsForValue().ser("account:id"+id,money);
}
public Double findMoneyById(Integer id){
Object money = redisTemplate.opsForValue().get("account:id"+id);
return new Doubble(money.toString());
}
四、事务底层原理
策略模式:
- 策略模式(Strategy pattern)使用不同策略的对象实现不同行为方式,策略对象的变化导致行为的变化。
- 策略模式(Strategy Pattern)使用不同策略的对象实现不同的行为方式,策略对象变化导致行为的变化
public Account findById(Integer id){
String sql = "SELECT * FROM account WHRER id =?";
RowMapper<Account> rm = new RowMapper<Account>(){
public Account mapRow(ResultSet rs,int rowNum) throws SQLExpection{
Account account = new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
return account;
}
};
return jdbcTemplate.queryForObject(sql,rm,id);
}
public List<Account> findAll(){
String sql = "SELECT * FROM account";
return jdbcTemplate.query(sql,new BeanPropertyRowMapper<Account>(Account.class));
}
总结
主要就是针对事务的两种表现形式