• 系列
  • 概述
  • 使用Transactional注解
    • txannotation-driven其他属性
    • 关于Transaction的属性
    • 在何处标注Transactional注解
    • 在方法处使用注解
    • 使用不同的事务管理器
  • 示例

系列

Spring对事务管理的支持概述以及 编程式的事务管理

Spring JDBC-使用XML配置声明式事务

Spring JDBC-使用注解配置声明式事务


概述

除了基于XML的事务配置,Spring还提供了基于注解的事务配置,即通过@Transactional对需要事务增强的Bean接口、实现类或者方法进行标注:在容器中配置基于注解的事务增强驱动,即可以启用基于注解的声明式事务


使用@Transactional注解

我们来对Spring JDBC-使用XML配置声明式事务中的例子使用@Transactional对基于aop/tx命名空间的事务配置进行改造,我们来感受下二者在使用方式上的差异。

@Service
@Transactional // 对业务类进行事务增强的标注
public class TeacherService {private TeacherDao teacherDao;public void addTeacher(Teacher teacher) {teacherDao.addTeacher(teacher);}public void updateTeacher(Teacher teacher) {teacherDao.updateTeacher(teacher);}public void getTeacherById(int teacherId) {teacherDao.getTeacher(teacherId);}public void addStudentForTeacher(Teacher teacher, Student student) {teacher.setStudent(student);teacherDao.addStudent(student);}
}

因为注解本身具有一组普适性的默认事务属性,所以往往只需要在需要事务管理的业务类中添加一个@Transactional注解,就完成了业务类事务属性的配置.

当然,注解只是提供元数据,它本身并不能完成事务切面织入的功能,因此,还需要在Spring中配置文件中通过一行小小的配置“通知”Spring容器对标注@Transactional注解的Bean进行加工处理,如下

<!--基于数据源的事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"p:dataSource-ref="dataSource"/><!--对标注了@Transactional注解Bean进行加工处理,以织入事务管理切面-->
<tx:annotation-driven transaction-manager="transactionManager"/>

在默认情况下,<tx:annotation-driven>会自动使用名为transactionManager事务管理器, 所以,如果我们的事务管理器的id为transactionManager,如上所示,则可以进一步简化为

<tx:annotation-driven/>

<tx:annotation-driven>其他属性

  • proxy-target-class: 如果为true ,Spring将通过创建子类来代理业务类,若果为false,则使用基于接口的代理。 如果使用子类代理,,需要在类路径中添加CGlib.jar类库

  • order:如果业务类除了事务切面外,还要织入其他的切面,则通过该属性可以控制事务切面在目标连接点的织入顺序。

  • mode: 模式 ,默认为proxy ,可以选择aspectj

关于@Transaction的属性

基于@Transactional注解的配置和基于XML的配置方式一样,它拥有一组普适性很强的默认事务属性,往往可以直接使用这些默认的属性

  • 事务传播行为: PROPAGATION_REQUIRED
  • 事务隔离级别:ISOLATION_DEFAULT
  • 读写事务属性:读/写事务
  • 超时时间:依赖底层的事务属性的默认值
  • 回滚设置:任何运行期异常引发回滚,任何检查型异常不会已发回滚。

因为这些默认设置在大多数情况下是都是适用的,所以一般不需要手工设置事务注解的属性(如下面的表格),当然Spring允许通过手工设定属性值覆盖默认值。

属性名 说明
propagation 事务传播行为,通过org.springframework.transaction.annotation.Propagation枚举类,提供合法值,比如@Transactional(propagation=Propagation.REQUIRES_NEW)
isolation 事务的隔离级别,通过org.springframework.transaction.annotation.Isolation枚举类,提供合法值,比如@Transactional(isolation=Isolation.READ_COMMITED)
readOnly 事务读写属性,布尔型,比如 @Transactional(readOnly=true)
timeout 超时时间,int型,单位为秒,例如 @Transactional(timeout=10)
rollbackFor 一组异常类,遇到时进行回滚,类型为 Class[],比如@Transactional(rollbackFor={SQLException,class})。 多个异常之间使用逗号分隔
rollbackForClassName 组异常类,遇到时进行回滚,类型为Strin[],默认值为{},比如@Transactional(rollbackForClassName={“Exception”})
noRollbackFor 一组异常类,遇到时不回滚,类型为 Class[],默认值为{}
noRolbackForClassName 一组异常类,遇到时不回滚,类型为 String[],默认值为{}

在何处标注@Transactional注解

@Transactional注解可以被应用于接口定义和接口方法、类定义和类的Public方法上。

但是Spring建议在业务的实现类上使用@Transactional注解,当然也可以在业务接口上使用@Transactional注解,但是这样会遗留下一些容易被忽视的隐患, 因为注解不能被继承,所以在业务接口中标注的@Transactional注解不会被业务实现类继承。 如果通过以下配置启用了代理类

<tx:annotation-driven transaction-manager="transactionManager"  proxy-target="true"/>

那么业务类不会添加事务增强,照样工作在非事务环境下。 举个例子,如果使用子类代理,假设用户为 XXX接口标注了@Transaction注解,那么其实现类XXXImpl依旧不会启用事务机制。

因此,Spring建议在具体业务类上使用@Transactional注解,这样不管tx:annotation-driven将proxy-target设置为true还是false,业务类都会启用事务机制

@Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果我们在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。


在方法处使用注解

方法处的注解会覆盖类定义的注解,如果有些方法需要使用特殊的事务属性,则可以在类注解的基础上提供方法注解,比如

@Repository
@Transactional // (1)类级注解,适用于类中所有的public方法
public class TeacherDaoImpl extends BaseDao implements TeacherDao {private Logger logger = Logger.getLogger(TeacherDaoImpl.class);private static final String addTeacherSQL = "insert into teacher(id,name,age,sex) values(teacher_id_seq.nextval,?,?,?)";private static final String queryTeacherByIdSQL = "select name ,age ,sex from teacher where id = ?";@Transactional(readOnly=true) // (2)提供额外的注解信息,它将覆盖(1)处的类级注解@Overridepublic Teacher getTeacher(int teacherId) {logger.info("TeacherID:" + teacherId);final Teacher teacher = new Teacher();jdbcTemplate.query(queryTeacherByIdSQL, new Object[] { teacherId },new RowCallbackHandler() {@Overridepublic void processRow(ResultSet rs) throws SQLException {teacher.setAge(rs.getInt("age"));teacher.setName(rs.getString("name"));teacher.setSex(rs.getString("sex"));}});return teacher;}}

(2)处的方法注解提供了readOnly属性,它将覆盖类级注解中默认的readOnly=false设置


使用不同的事务管理器

一般情况下,一个应用仅需要使用一个事务管理器, 如果希望在不同的地方使用不同的事务管理器,则可以通过如下方式实现

配置文件:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 扫描类包,将标注Spring注解的类自动转化Bean,同时完成Bean的注入 --><context:component-scan base-package="com.xgj.dao.transaction.multiTxManager" /><!-- 使用context命名空间,引入数据库的properties文件 --><context:property-placeholder location="classpath:spring/jdbc.properties" /><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close" p:driverClassName="${jdbc.driverClassName}"p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}" /><!-- 配置Jdbc模板 --><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"p:dataSource-ref="dataSource" /><!--基于数据源的事务管理器,通过属性引用数据源  可以使用dataSource-ref引用不同的数据源,我们这里只展示同一个--><bean id="forumTxManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"p:dataSource-ref="dataSource"><!-- 为事务管理器指定一个名字 --><qualifier value="forum"/></bean><bean id="topicTxManger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"p:dataSource-ref="dataSource"><!-- 为事务管理器指定一个名字 --><qualifier value="topic"/></bean><!-- 通知Spring处理注解Bean --><tx:annotation-driven/></beans>

使用

package com.xgj.dao.transaction.multiTxManager;import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service
public class MulitTxServiceWitSpecificName {// (1)使用名为forum的事务管理器@Transactional("forum")public void addForum() {}// 使用名为topic的事务管理器@Transactional("topic")public void addTopic() {}
}

在(1)处我们为事务管理器指定了一个数据源,每个事务管理器都可以绑定一个独立的数据源。

在spring配置文件中

<!-- 为事务管理器指定一个名字 --><qualifier value="forum"/>

指定了一个可以被@Transactional注解引用的事务管理器的标识。

我们发现在代码中使用 @Transactional(“forum”) 来引用特定的事务管理器,如果很多地方都需要使用,则显得很麻烦,我们可以通过自定义注解进行标识

package com.xgj.dao.transaction.multiTxManager;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;import org.springframework.transaction.annotation.Transactional;@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
// 绑定到forum的事务管理器中
@Transactional("forum")
public @interface ForumTransactional {}

引用的话,调整下代码,如下

package com.xgj.dao.transaction.multiTxManager;import org.springframework.stereotype.Service;@Service
public class MulitTxServiceWithSelfDefineAnno {// 使用名为forum的事务管理器@ForumTransactionalpublic void addForum() {}// 使用名为topic的事务管理器@TopicTransactionalpublic void addTopic() {}
}

示例

代码已托管到Github—> https://github.com/yangshangwei/SpringMaster

Spring JDBC-使用注解配置声明式事务相关推荐

  1. Spring JDBC-使用XML配置声明式事务

    系列 概述 基于aop/tx命名空间的配置 示例 tx:method元素属性 系列 Spring对事务管理的支持概述以及 编程式的事务管理 Spring JDBC-使用XML配置声明式事务 Sprin ...

  2. Spring→事务、隔离级别、事务传播行为、编程式事务控制、XML配置声明式事务(原始方式)、XML配置声明式事务(基于tx/aop)、@注解配置声明式事务、优势总结

    事务 Spring事务管理 不考虑隔离引发问题 隔离级别 事务传播行为 演示环境搭建 编程式事务控制 XML配置声明式事务(原始方式) XML配置声明式事务(基于tx/aop) @注解配置声明式事务 ...

  3. 注解配置声明式事务控制解析

    ①使用 @Transactional 在需要进行事务控制的类或是方法上修饰,注解可用的属性同 xml 配置方式,例如隔离级别.传播行为等. ②注解使用在类上,那么该类下的所有方法都使用同一套注解参数配 ...

  4. 【Spring】spring基于纯注解的声明式事务控制

    结构 去掉bean.xml config JdbcConfig package com.itheima.config;import org.springframework.beans.factory. ...

  5. spring基于纯注解的声明式事务控制

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...

  6. 使用注解配置声明式事务控制

    编写 AccoutDao @Repository("accountDao") public class AccountDaoImpl implements AccountDao { ...

  7. 【Spring】spring基于注解的声明式事务控制

    结构 domin package com.itheima.domain;import java.io.Serializable;public class Account implements Seri ...

  8. spring基于注解的声明式事务控制

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...

  9. spring 注解开启声明式事务

    spring开启声明式事务: 导入依赖: pom.xml <dependencies><!-- https://mvnrepository.com/artifact/org.spri ...

最新文章

  1. Android动态加载黑科技 动态创建Activity模式
  2. WebSocket+MSE——HTML5 直播技术解析
  3. [LeetCode]Distinct Subsequences,解题报告
  4. 基于多线程的TCP局域网通信,客户端向服务端上传 文件简单实现源码
  5. 电子计算机诞生于1946年第几台,人类第一台电子计算机诞生于1946年2月
  6. java自学-基本数据类型
  7. bash:pip:找不到命令
  8. Niushop开源微信商城+小程序商城源码
  9. python爬虫百度文库源码_Python爬取百度文库学习
  10. MATLAB拟合函数
  11. 脑电时频分析II:时频分析
  12. windwos常用cmd(DOS)命令集合
  13. 前端导出表格,万级数据,带样式(留自用)
  14. 大三软件测试实习生面试经验-1
  15. 006. 分割回文串
  16. WPS 加载项开发说明
  17. 树莓派ASP.NET环境配置
  18. Python3网络爬虫使用User Agent和代理IP隐藏身份
  19. 新概念英语(1-99)Ow!
  20. html 平铺 布局,html – 具有一致边距和对齐的Flexbox平铺布局

热门文章

  1. pycharm 中写代码的提示的前符号 p,m ,c,v, f 是什么意思
  2. python爬取动态网站
  3. Ubuntu nginx 配置实例
  4. tf.reverse
  5. tf.split()
  6. 剪切粘贴时总是上次的内容_【Procreate 迷你课堂】#4 三指快速拷贝及粘贴
  7. 强化学习笔记:Q-learning :temporal difference 方法
  8. 深度学习核心技术精讲100篇(六十四)-特征选择原理及应用实战案例
  9. 机器学习算法与Python实践之(三)支持向量机(SVM)进阶
  10. Python 模块学习 logging(2)