日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

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

發布時間:2025/3/21 javascript 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring JDBC-使用注解配置声明式事务 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  • 系列
  • 概述
  • 使用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-使用注解配置声明式事务的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。