Spring事務(wù)管理中關(guān)于數(shù)據(jù)庫(kù)連接池詳解
Spring事務(wù)管理
事務(wù)(Transaction),一般是指要做的或所做的事情。在計(jì)算機(jī)術(shù)語(yǔ)中是指訪問(wèn)并可能更新數(shù)據(jù)庫(kù)中各種數(shù)據(jù)項(xiàng)的一個(gè)程序執(zhí)行單元。事務(wù)通常由高級(jí)數(shù)據(jù)庫(kù)操縱語(yǔ)言或編程語(yǔ)言(如SQL,C++或Java)書(shū)寫(xiě)的用戶程序的執(zhí)行所引起,并用形如begin transaction
和end transaction
語(yǔ)句(或函數(shù)調(diào)用)來(lái)界定。事務(wù)由事務(wù)開(kāi)始(begin transaction
)和事務(wù)結(jié)束(end transaction
)之間執(zhí)行的全體操作組成
概念:
例如:在關(guān)系數(shù)據(jù)庫(kù)中,一個(gè)事務(wù)可以是一條SQL語(yǔ)句,一組SQL語(yǔ)句或整個(gè)程序
事務(wù)ACID原則:
- 原子性(atomicity):一個(gè)事務(wù)是一個(gè)不可分割的工作單位,事務(wù)中包括的操作要么都做,要么都不做
- 一致性(consistency):事務(wù)必須是使數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài)變到另一個(gè)一致性狀態(tài)。一致性與原子性密切相關(guān)
- 隔離性(isolation):一個(gè)事務(wù)的執(zhí)行不能被其他事務(wù)干擾。即一個(gè)事務(wù)內(nèi)部的操作及使用的數(shù)據(jù)對(duì)并發(fā)的其他事務(wù)是隔離的,并發(fā)執(zhí)行的各個(gè)事務(wù)之間不能互相干擾
- 持久性(durability):持久性也稱(chēng)永久性(permanence),指一個(gè)事務(wù)一旦提交,它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變就應(yīng)該是永久性的。接下來(lái)的其他操作或故障不應(yīng)該對(duì)其有任何影響
聲明式事務(wù)
通過(guò)AOP
(面向切面)方式在方法前使用編程式事務(wù)的方法開(kāi)啟事務(wù),通過(guò)注解或XML配置實(shí)現(xiàn),在方法后提交或回滾。用配置文件的方法或注解方法(如:@Transactional)控制事務(wù)
編程式事務(wù):代碼中進(jìn)行事務(wù)管理
手動(dòng)開(kāi)啟、提交、回滾事務(wù)
環(huán)境搭建
User類(lèi)
package com.wei.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private String pwd; }
UserMapper接口
package com.wei.Mapper; import com.wei.pojo.User; import java.util.List; public interface UserMapper { //查詢(xún)用戶 public List<User> selectUser(); //添加用戶 public int addUser(User user); //刪除用戶 public int deleteUser(int id); }
UserMapper.xml接口映射文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--namespace=綁定一個(gè)對(duì)應(yīng)的Dao/Mapper接口--> <mapper namespace="com.wei.Mapper.UserMapper"> <!--select查詢(xún)語(yǔ)句查詢(xún)?nèi)坑脩?-> <select id="selectUser" resultType="com.wei.pojo.User"> select * from mybatis.user; </select> <insert id="addUser" parameterType="user"> insert into mybatis.user (id, name, pwd) values (#{id}, #{name}, #{pwd}); </insert> <delete id="deleteUser" parameterType="int"> deletes from mybatis.user where id=#{id}; </delete> </mapper>
mybatis-config.xml核心配置文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <!--configuration核心配置文件--> <configuration> <!--引入外部配置文件--> <!--<properties resource="jdbc.properties"/>--> <settings> <!--標(biāo)準(zhǔn)日志工廠實(shí)現(xiàn)--> <setting name="logImpl" value="LOG4J"/> </settings> <typeAliases> <package name="com.wei.pojo"/> </typeAliases> <!--環(huán)境配置--> <environments default="development"> <environment id="development"> <!--事物管理--> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> </configuration>
Spring-dao.xml(配置、整合Mybatis)
<?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:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd "> <!--DataSource:使用Spring的數(shù)據(jù)源替換Mybatis的配置--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <!--sqlSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!--配置數(shù)據(jù)源--> <property name="dataSource" ref="dataSource"/> <!--綁定Mybatis配置文件--> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath:com/wei/Mapper/*.xml"/> </bean> <!--配置聲明式事務(wù)--> <!--要開(kāi)啟 Spring 的事務(wù)處理功能,在 Spring 的配置文件中創(chuàng)建一個(gè) DataSourceTransactionManager 對(duì)象--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--<property name="dataSource" ref="dataSource"/>--> <constructor-arg ref="dataSource" /> </bean> </beans>
applicationContext.xml(配置Spring框架所需的信息)
package com.wei.Mapper; import com.wei.pojo.User; import org.mybatis.spring.support.SqlSessionDaoSupport; import java.util.List; public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{ public List<User> selectUser(){ User user = new User(5, "haha", "123456"); UserMapper mapper = getSqlSession().getMapper(UserMapper.class); mapper.addUser(user); mapper.deleteUser(5); return mapper.selectUser(); } @Override public int addUser(User user) { UserMapper mapper = getSqlSession().getMapper(UserMapper.class); return mapper.addUser(user); } @Override public int deleteUser(int id) { UserMapper mapper = getSqlSession().getMapper(UserMapper.class); return mapper.deleteUser(1); } }
標(biāo)準(zhǔn)配置
要開(kāi)啟 Spring 的事務(wù)處理功能,在 Spring 的配置文件中創(chuàng)建一個(gè) DataSourceTransactionManager
對(duì)象:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <constructor-arg ref="dataSource" /> </bean>
@Configuration public class DataSourceConfig { @Bean public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } }
聲明式事務(wù)
spring-dao.xml中配置事務(wù)
<?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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <!--DataSource:使用Spring的數(shù)據(jù)源替換Mybatis的配置--> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <!--sqlSessionFactory--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!--配置數(shù)據(jù)源--> <property name="dataSource" ref="dataSource"/> <!--綁定Mybatis配置文件--> <property name="configLocation" value="classpath:mybatis-config.xml"/> <property name="mapperLocations" value="classpath:com/wei/Mapper/*.xml"/> </bean> <!--配置聲明式事務(wù)--> <!--要開(kāi)啟 Spring 的事務(wù)處理功能,在 Spring 的配置文件中創(chuàng)建一個(gè) DataSourceTransactionManager 對(duì)象--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--<property name="dataSource" ref="dataSource"/>--> <constructor-arg ref="dataSource" /> </bean> <!--結(jié)合AOP實(shí)現(xiàn)事務(wù)的織入--> <!--配置事務(wù)通知advice--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <!--給那些方法配置事務(wù)--> <!--配置事務(wù)的傳播特性:new propagation --> <tx:attributes> <tx:method name="add" propagation="REQUIRED"/> <tx:method name="delete" propagation="REQUIRED"/> <tx:method name="update" propagation="REQUIRED"/> <tx:method name="select" propagation="REQUIRED"/> <tx:method name="query" read-only="true"/> <!--所有方法配置事務(wù)--> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!--AOP:配置事務(wù)切入--> <aop:config> <!--配置事務(wù)切入點(diǎn)pointcut--> <aop:pointcut id="txPointCut" expression="execution(* com.wei.Mapper.*.*(..))"/> <!--配置事務(wù)顧問(wèn)advisor切入,將事務(wù)txAdvice切入到txPointCut--> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/> </aop:config> </beans>
測(cè)試類(lèi)
import com.wei.Mapper.UserMapper; import com.wei.pojo.User; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.List; public class MyTest { @Test public void test(){ //解析beans.xml文件,生成管理相應(yīng)的Bean對(duì)象,創(chuàng)建 Spring 的 IOC 容器 ApplicationContext context = new ClassPathXmlApplicationContext("applicicationContext.xml"); //getBean:參數(shù)即為Spring配置文件中的bean的id //從IOC容器中獲取 bean 的實(shí)例 UserMapper userMapper = context.getBean("userMapper", UserMapper.class); List<User> userList = userMapper.selectUser(); for (User user : userList) { System.out.println(user); } } }
isolation:隔離級(jí)別
no-rollback-for:不回滾
propagation:傳播行為
REQUIRED:支持當(dāng)前事務(wù),如果當(dāng)前沒(méi)有事務(wù),就新建一個(gè)事務(wù)(默認(rèn))
NESTED:支持當(dāng)前事務(wù),如果當(dāng)前事務(wù)存在,則執(zhí)行一個(gè)嵌套事務(wù),如果當(dāng)前沒(méi)有事務(wù),就新建一個(gè)事務(wù)
read-only:只讀
rollback-for:回滾控制
timeout:過(guò)期時(shí)間
總結(jié)
配置事務(wù)原因:
- 避免數(shù)據(jù)提交不一致
- 事務(wù)涉及數(shù)據(jù)一致性和完整性問(wèn)題
SqlSessionFactory
SqlSessionFactory是MyBatis的核心對(duì)象,用于初始化MyBatis,讀取配置文件,創(chuàng)建SqlSession對(duì)象,SqlSessionFactory是全局對(duì)象,為保證其在應(yīng)用中全局唯一,要使用static進(jìn)行初始化
SqlSession是MyBatis操作數(shù)據(jù)庫(kù)的核心對(duì)象,SqlSession使用JDBC方式與數(shù)據(jù)庫(kù)交互,同時(shí)提供了數(shù)據(jù)表的CRUD(增刪改查)對(duì)應(yīng)的api方法
導(dǎo)入jar包
格式:
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>x.x.x</version> </dependency>
<!--mybatis--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency>
XML中構(gòu)建SqlSessionFactory
- 每個(gè)基于 MyBatis 的應(yīng)用都是以一個(gè) SqlSessionFactory 的實(shí)例為核心
- SqlSessionFactory 的實(shí)例可以通過(guò) SqlSessionFactoryBuilder 獲得
- 而 SqlSessionFactoryBuilder 則可以從 XML 配置文件或一個(gè)預(yù)先配置的 Configuration 實(shí)例來(lái)構(gòu)建出 SqlSessionFactory 實(shí)例
獲取sqlSessionFaction對(duì)象
String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
獲得SqlSession的實(shí)例
既然有了 SqlSessionFactory,顧名思義,我們可以從中獲得 SqlSession 的實(shí)例。SqlSession 提供了在數(shù)據(jù)庫(kù)執(zhí)行 SQL 命令所需的所有方法。你可以通過(guò) SqlSession 實(shí)例來(lái)直接執(zhí)行已映射的 SQL 語(yǔ)句
SqlSession sqlSession = sessionFactory.openSession(true);
代碼實(shí)現(xiàn)
utils包下創(chuàng)建工具類(lèi)MybatisUtils類(lèi)
package com.wei.utils; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; //sqlSessionFactory 構(gòu)造 sqlSession public class MybatisUtils { //提升作用域:定義SqlSessionFactory全局變量 private static SqlSessionFactory sqlSessionFactory; //靜態(tài)代碼塊:執(zhí)行優(yōu)先級(jí)高于非靜態(tài)的初始化塊,它會(huì)在類(lèi)初始化的時(shí)候執(zhí)行一次,執(zhí)行完成便銷(xiāo)毀,它僅能初始化類(lèi)變量,即static修飾的數(shù)據(jù)成員 static { try { //使用Mybatis第一步:獲取sqlSessionFactory對(duì)象 //定義核心配置文件 String resource = "mybatis-config.xml"; //通過(guò)IO流加載resource的mybatis-config.xml核心配置文件文件 InputStream inputStream = Resources.getResourceAsStream(resource); //通過(guò)build加載inputStream sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } //既然有了 SqlSessionFactory,顧名思義,我們可以從中獲得 SqlSession 的實(shí)例。 //SqlSession 提供了在數(shù)據(jù)庫(kù)執(zhí)行 SQL 命令所需的所有方法。 //你可以通過(guò) SqlSession 實(shí)例來(lái)直接執(zhí)行已映射的 SQL 語(yǔ)句 public static SqlSession getSqlSession(){ return sqlSessionFactory.openSession(true); //此處設(shè)置參數(shù)為true時(shí),表示開(kāi)啟自動(dòng)提交事物功能 } }
作用域(Scope)和生命周期
所有代碼中都遵循這種使用模式,可以保證所有數(shù)據(jù)庫(kù)資源都能被正確地關(guān)閉
SqlSessionFactoryBuilder(構(gòu)造器)
一旦創(chuàng)建了 SqlSessionFactory,就不再需要它了
局部變量
SqlSessionFactory(工廠)
- SqlSessionFactory 一旦被創(chuàng)建就應(yīng)該在應(yīng)用的運(yùn)行期間一直存在,沒(méi)有任何理由丟棄它或重新創(chuàng)建另一個(gè)實(shí)例
- 數(shù)據(jù)庫(kù)連接池
- SqlSessionFactory 的最佳作用域是應(yīng)用作用域
- 最簡(jiǎn)單的就是使用單例模式或者靜態(tài)單例模式
SqlSession(會(huì)話)
- 連接到SqlSessionFactory(連接池)的一個(gè)請(qǐng)求
- SqlSession 的實(shí)例不是線程安全的,因此是不能被共享的,所以它的最佳的作用域是請(qǐng)求或方法作用域。
- 使用完需要趕緊關(guān)閉,否則資源被占用 SqlSession.close()
到此這篇關(guān)于Spring事務(wù)管理中關(guān)于數(shù)據(jù)庫(kù)連接池詳解的文章就介紹到這了,更多相關(guān)Spring數(shù)據(jù)庫(kù)連接池內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java如何重寫(xiě)object類(lèi)的equals方法詳解
這篇文章主要給大家介紹了關(guān)于Java如何重寫(xiě)object類(lèi)的equals方法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12Springboot打包為Docker鏡像并部署的實(shí)現(xiàn)
這篇文章主要介紹了Springboot打包為Docker鏡像并部署的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12Java獲取時(shí)間如何將當(dāng)前時(shí)間減一天、一月、一年、并格式化
這篇文章主要介紹了Java獲取時(shí)間,將當(dāng)前時(shí)間減一天、一月、一年,并加以格式化,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09MyBatis快速入門(mén)(簡(jiǎn)明淺析易懂)
MyBatis是支持普通SQL查詢(xún),存儲(chǔ)過(guò)程和高級(jí)映射的優(yōu)秀持久層框架。mybatis的學(xué)習(xí)是程序員的必修課。今天小編通過(guò)分享本教程幫助大家快速入門(mén)mybatis,對(duì)mybatis入門(mén)知識(shí)感興趣的朋友參考下吧2016-11-11Spring-boot JMS 發(fā)送消息慢的解決方法
這篇文章主要為大家詳細(xì)介紹了Spring-boot JMS 發(fā)送消息慢的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08Mybatis調(diào)用存儲(chǔ)過(guò)程的案例
這篇文章主要介紹了Mybatis如何調(diào)用存儲(chǔ)過(guò)程,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07Springboot maven plugin插件原理及作用
這篇文章主要介紹了Springboot maven plugin插件原理及作用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10關(guān)于Arrays.sort()使用的注意事項(xiàng)
這篇文章主要介紹了關(guān)于Arrays.sort()使用的注意事項(xiàng),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05