javascript
Spring系列教程八: Spring实现事务的两种方式
2019獨角獸企業重金招聘Python工程師標準>>>
一、 Spring事務概念:
事務是一系列的動作,它們綜合在一起才是一個完整的工作單元,這些動作必須全部完成,如果有一個失敗的話,那么事務就會回滾到最開始的狀態,仿佛什么都沒發生過一樣。
?在企業級應用程序開發中,事務管理必不可少的技術,用來確保數據的完整性和一致性。?
事務有四個特性:ACID
-
原子性(Atomicity):事務是一個原子操作,由一系列動作組成。事務的原子性確保動作要么全部完成,要么完全不起作用。
-
一致性(Consistency):一旦事務完成(不管成功還是失敗),系統必須確保它所建模的業務處于一致的狀態,而不會是部分完成部分失敗。在現實中的數據不應該被破壞。
-
隔離性(Isolation):可能有許多事務會同時處理相同的數據,因此每個事務都應該與其他事務隔離開來,防止數據損壞。
-
持久性(Durability):一旦事務完成,無論發生什么系統錯誤,它的結果都不應該受到影響,這樣就能從任何系統崩潰中恢復過來。通常情況下,事務的結果被寫到持久化存儲器中。
?舉個簡單的例子:例如陳多多給陳多糖轉錢,但是在轉錢的過程中出現了問題,銀行系統出現了問題,那么陳多多的錢給陳多糖轉過去了,但是陳多糖卻沒有收到錢?這個就很尷尬
那么怎么避免?出現這個問題啦?這個時候就要用到我們spring中的事務管理
二、用xml的方式實現事務管理
第一步、導jar包
<dependencies><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><!-- spring start --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>LATEST</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>LATEST</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-instrument</artifactId><version>LATEST</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>LATEST</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-oxm</artifactId><version>LATEST</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-messaging</artifactId><version>LATEST</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>LATEST</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>LATEST</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>LATEST</version></dependency><!-- spring end --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version></dependency><dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.15</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.0</version><scope>provided</scope></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.2</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.0</version></dependency><!-- https://mvnrepository.com/artifact/aspectj/aspectjrt --><dependency><groupId>aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.5.4</version></dependency><!-- https://mvnrepository.com/artifact/aspectj/aspectjweaver --><dependency><groupId>aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.5.4</version></dependency></dependencies><build><resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include></includes><filtering>false</filtering></resource></resources></build>第二步、創建Mapper接口和實體類
package com.bdqn.zmj.dao;import com.bdqn.zmj.entity.user;import java.util.List;public interface UserMapper {List<user> GetList();//轉出void jian();//轉入void add(); } package com.bdqn.zmj.entity;public class user {int uid;String uname;int money;//注意這里對應的是映射文件里的UserId,而不是這類里的uidpublic int getUserId() {return uid;}public void setUserId(int uid) {this.uid = uid;}public String getUserName() {return uname;}public void setUserName(String uname) {this.uname = uname;}public int getMoney() {return money;}public void setMoney(int money) {this.money = money;} }第三步、創建mybatis映射文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.bdqn.zmj.dao.UserMapper"><resultMap id="userMap" type="user"><id property="userId" column="uid" /><result property="userName" column="uname"/><result property="money" column="money" /></resultMap><select id="GetList" resultMap="userMap">select * from t_user</select><update id="jian">update t_user set money = money-500 where uid =1</update><update id="add">update t_user set money = money +500 where uid =2</update> </mapper>第四步、Service層代碼
package com.bdqn.zmj.service;import com.bdqn.zmj.dao.UserMapper; import com.bdqn.zmj.entity.user; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;import java.util.List; /* * 事務一般都加在service層,因為service調用dao * 當servoce調用多個dao方法的時候事務如下處理 * 加載controller層:當controller調用多個service方法發的時候事務如何處理 * * */ @Service public class UserService{@AutowiredUserMapper dao;public List<user> GetList(){return dao.GetList();}@Transactionalpublic void transfer() {dao.jian();int i = 10/0;dao.add();} }第五步、ApplicationContext配置文件、mybatis映射文件、Log4J配置文件、數據庫配置文件
<?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:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"><context:component-scan base-package="com.bdqn.zmj"/><!--注入配置文件--><context:property-placeholder location="classpath:db.properties"/><!--兩個框架整合:幾乎所有的配置都交給了spring,因為spring專門做整合--><!--1.數據源--><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${driver}"/><property name="jdbcUrl" value="${url}"/><property name="user" value="${user}"/><property name="password" value="${password}"/><!--其他數據庫連接池配置省略,比如:連接個數,最大連接數。。。。--></bean><!--配置sqlSessionFactiorBean--><bean id="sessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="configLocation" value="classpath:mybatis-config.xml"></property><property name="mapperLocations" value="com/bdqn/zmj/mapper/*.xml"></property><property name="dataSource" ref="dataSource"></property></bean><!--配置接口掃描--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.bdqn.zmj.dao"/><property name="sqlSessionFactoryBeanName" value="sessionFactoryBean"/></bean><!--配置事務管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean>配置事務傳播行為,就是 有事務的方法調用 沒有事務的方法的時候,事務應該如何傳遞<tx:advice id="txadvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="transfer" propagation="REQUIRED"/></tx:attributes></tx:advice><!--配置切面--><aop:config><aop:pointcut id="pointcut" expression="execution(* com.bdqn.zmj..*.*(..))"/><aop:advisor advice-ref="txadvice" pointcut-ref="pointcut"/></aop:config> </beans> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <!--通過這個配置文件,完成mybatis與數據庫的連接 --> <configuration><settings><setting name="logImpl" value="LOG4J"/></settings><!-- 設置類的別名 --><typeAliases><!-- <typeAlias alias="User" type="com.wu.pojo.User"/> --><!-- 根據包取別名,把包下面的所有類都按類名來取別名 --><!-- 這用可以簡化代碼量 --><package name="com.bdqn.zmj.entity"/></typeAliases></configuration> log4j.rootLogger=info,CONSOLE ############################################################# # Console Appender ############################################################# log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.Threshold=info ##log4j.appender.CONSOLE.DatePattern=yyyy-MM-dd log4j.appender.CONSOLE.Target=System.out log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern= %d{yyyy-M-d HH:mm:ss}%x[%5p] %m%n driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/fresh?serverTimezone=UTC user=root password=root第六步、編寫測試類
package com.bdqn.zmj.test;import com.bdqn.zmj.entity.user; import com.bdqn.zmj.service.UserService; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.transaction.annotation.Transactional;import java.util.List;public class Testone {ApplicationContext context = null;@Beforepublic void load(){context = new ClassPathXmlApplicationContext("applicationContext.xml");}@Test//事務,下面的方法只有全執行和全不執行兩種狀態public void test2(){UserService service = context.getBean("userService", UserService.class);service.transfer();} }數據庫中的數據沒有變化,操作失敗,數據回滾回去了!!!
二、用注解的方式實現事務管理
只需要改變兩個地方即可
第一、service層,方法上加上?@Transactional
package com.bdqn.zmj.service;import com.bdqn.zmj.dao.UserMapper; import com.bdqn.zmj.entity.user; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional;import java.util.List; /* * 事務一般都加在service層,因為service調用dao * 當servoce調用多個dao方法的時候事務如下處理 * 加載controller層:當controller調用多個service方法發的時候事務如何處理 * * */ @Service public class UserService{@AutowiredUserMapper dao;public List<user> GetList(){return dao.GetList();}@Transactionalpublic void transfer() {dao.jian();int i = 10/0;dao.add();} }第二步、ApplicationContext.xml中,只留下配置事務管理器、然后加上掃描事務的<tx:annotation-driven />
<?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:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd"><context:component-scan base-package="com.bdqn.zmj"/><!--注入配置文件--><context:property-placeholder location="classpath:db.properties"/><!--兩個框架整合:幾乎所有的配置都交給了spring,因為spring專門做整合--><!--1.數據源--><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${driver}"/><property name="jdbcUrl" value="${url}"/><property name="user" value="${user}"/><property name="password" value="${password}"/><!--其他數據庫連接池配置省略,比如:連接個數,最大連接數。。。。--></bean><!--配置sqlSessionFactiorBean--><bean id="sessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="configLocation" value="classpath:mybatis-config.xml"></property><property name="mapperLocations" value="com/bdqn/zmj/mapper/*.xml"></property><property name="dataSource" ref="dataSource"></property></bean><!--配置接口掃描--><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.bdqn.zmj.dao"/><property name="sqlSessionFactoryBeanName" value="sessionFactoryBean"/></bean><!--配置事務管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!--配置事務傳播行為,就是 有事務的方法調用 沒有事務的方法的時候,事務應該如何傳遞--><!--<tx:advice id="txadvice" transaction-manager="transactionManager">--><!--<tx:attributes>--><!--<tx:method name="transfer" propagation="REQUIRED"/>--><!--</tx:attributes>--><!--</tx:advice>--><!--<!–配置切面–>--><!--<aop:config>--><!--<aop:pointcut id="pointcut" expression="execution(* com.bdqn.zmj..*.*(..))"/>--><!--<aop:advisor advice-ref="txadvice" pointcut-ref="pointcut"/>--><!--</aop:config>--><tx:annotation-driven /> </beans>這兩種方式都可以實現事務配置、但是我們不配置細節的話,用的都是注解的方式、xml方式用于比較細致的配置,比如什么銀行轉賬什么的
轉載于:https://my.oschina.net/u/4115727/blog/3054097
總結
以上是生活随笔為你收集整理的Spring系列教程八: Spring实现事务的两种方式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 声明式事务基于注解@Transactio
- 下一篇: 三星s10支持5g吗(三星智能手机)