Spring數(shù)據(jù)庫連接池實現(xiàn)原理深入刨析
Spring事務管理
事務(Transaction),一般是指要做的或所做的事情。在計算機術語中是指訪問并可能更新數(shù)據(jù)庫中各種數(shù)據(jù)項的一個程序執(zhí)行單元。事務通常由高級數(shù)據(jù)庫操縱語言或編程語言(如SQL,C++或Java)書寫的用戶程序的執(zhí)行所引起,并用形如begin transaction和end transaction語句(或函數(shù)調用)來界定。事務由事務開始(begin transaction)和事務結束(end transaction)之間執(zhí)行的全體操作組成
概念:
例如:在關系數(shù)據(jù)庫中,一個事務可以是一條SQL語句,一組SQL語句或整個程序
事務ACID原則:
- 原子性(atomicity):一個事務是一個不可分割的工作單位,事務中包括的操作要么都做,要么都不做
- 一致性(consistency):事務必須是使數(shù)據(jù)庫從一個一致性狀態(tài)變到另一個一致性狀態(tài)。一致性與原子性密切相關
- 隔離性(isolation):一個事務的執(zhí)行不能被其他事務干擾。即一個事務內部的操作及使用的數(shù)據(jù)對并發(fā)的其他事務是隔離的,并發(fā)執(zhí)行的各個事務之間不能互相干擾
- 持久性(durability):持久性也稱永久性(permanence),指一個事務一旦提交,它對數(shù)據(jù)庫中數(shù)據(jù)的改變就應該是永久性的。接下來的其他操作或故障不應該對其有任何影響
聲明式事務:
通過AOP(面向切面)方式在方法前使用編程式事務的方法開啟事務,通過注解或XML配置實現(xiàn),在方法后提交或回滾。用配置文件的方法或注解方法(如:@Transactional)控制事務
編程式事務:代碼中進行事務管理
手動開啟、提交、回滾事務
環(huán)境搭建
User類
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 {
//查詢用戶
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=綁定一個對應的Dao/Mapper接口-->
<mapper namespace="com.wei.Mapper.UserMapper">
<!--select查詢語句查詢全部用戶-->
<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>
<!--標準日志工廠實現(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>
<!--配置聲明式事務-->
<!--要開啟 Spring 的事務處理功能,在 Spring 的配置文件中創(chuàng)建一個 DataSourceTransactionManager 對象-->
<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);
}
}標準配置
要開啟 Spring 的事務處理功能,在 Spring 的配置文件中創(chuàng)建一個 DataSourceTransactionManager 對象:
<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());
}
}
聲明式事務
spring-dao.xml中配置事務
<?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>
<!--配置聲明式事務-->
<!--要開啟 Spring 的事務處理功能,在 Spring 的配置文件中創(chuàng)建一個 DataSourceTransactionManager 對象-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--<property name="dataSource" ref="dataSource"/>-->
<constructor-arg ref="dataSource" />
</bean>
<!--結合AOP實現(xiàn)事務的織入-->
<!--配置事務通知advice-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--給那些方法配置事務-->
<!--配置事務的傳播特性: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"/>
<!--所有方法配置事務-->
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!--AOP:配置事務切入-->
<aop:config>
<!--配置事務切入點pointcut-->
<aop:pointcut id="txPointCut" expression="execution(* com.wei.Mapper.*.*(..))"/>
<!--配置事務顧問advisor切入,將事務txAdvice切入到txPointCut-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
</beans>
測試類
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文件,生成管理相應的Bean對象,創(chuàng)建 Spring 的 IOC 容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicicationContext.xml");
//getBean:參數(shù)即為Spring配置文件中的bean的id
//從IOC容器中獲取 bean 的實例
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
List<User> userList = userMapper.selectUser();
for (User user : userList) {
System.out.println(user);
}
}
}isolation:隔離級別
no-rollback-for:不回滾
propagation:傳播行為
REQUIRED:支持當前事務,如果當前沒有事務,就新建一個事務(默認)
NESTED:支持當前事務,如果當前事務存在,則執(zhí)行一個嵌套事務,如果當前沒有事務,就新建一個事務
read-only:只讀
rollback-for:回滾控制
timeout:過期時間
總結
配置事務原因:
- 避免數(shù)據(jù)提交不一致
- 事務涉及數(shù)據(jù)一致性和完整性問題
SqlSessionFactory
SqlSessionFactory是MyBatis的核心對象,用于初始化MyBatis,讀取配置文件,創(chuàng)建SqlSession對象,SqlSessionFactory是全局對象,為保證其在應用中全局唯一,要使用static進行初始化
SqlSession是MyBatis操作數(shù)據(jù)庫的核心對象,SqlSession使用JDBC方式與數(shù)據(jù)庫交互,同時提供了數(shù)據(jù)表的CRUD(增刪改查)對應的api方法
導入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中構建SqlSessionFactory
- 每個基于 MyBatis 的應用都是以一個 SqlSessionFactory 的實例為核心
- SqlSessionFactory 的實例可以通過 SqlSessionFactoryBuilder 獲得
- 而 SqlSessionFactoryBuilder 則可以從 XML 配置文件或一個預先配置的 Configuration 實例來構建出 SqlSessionFactory 實例
獲取sqlSessionFaction對象
String resource = "org/mybatis/example/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
獲得SqlSession的實例
既然有了 SqlSessionFactory,顧名思義,我們可以從中獲得 SqlSession 的實例。SqlSession 提供了在數(shù)據(jù)庫執(zhí)行 SQL 命令所需的所有方法。你可以通過 SqlSession 實例來直接執(zhí)行已映射的 SQL 語句
SqlSession sqlSession = sessionFactory.openSession(true);
代碼實現(xiàn)
utils包下創(chuàng)建工具類MybatisUtils類
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 構造 sqlSession
public class MybatisUtils {
//提升作用域:定義SqlSessionFactory全局變量
private static SqlSessionFactory sqlSessionFactory;
//靜態(tài)代碼塊:執(zhí)行優(yōu)先級高于非靜態(tài)的初始化塊,它會在類初始化的時候執(zhí)行一次,執(zhí)行完成便銷毀,它僅能初始化類變量,即static修飾的數(shù)據(jù)成員
static {
try {
//使用Mybatis第一步:獲取sqlSessionFactory對象
//定義核心配置文件
String resource = "mybatis-config.xml";
//通過IO流加載resource的mybatis-config.xml核心配置文件文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//通過build加載inputStream
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//既然有了 SqlSessionFactory,顧名思義,我們可以從中獲得 SqlSession 的實例。
//SqlSession 提供了在數(shù)據(jù)庫執(zhí)行 SQL 命令所需的所有方法。
//你可以通過 SqlSession 實例來直接執(zhí)行已映射的 SQL 語句
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession(true); //此處設置參數(shù)為true時,表示開啟自動提交事物功能
}
}作用域(Scope)和生命周期


所有代碼中都遵循這種使用模式,可以保證所有數(shù)據(jù)庫資源都能被正確地關閉
SqlSessionFactoryBuilder(構造器)
一旦創(chuàng)建了 SqlSessionFactory,就不再需要它了
局部變量
SqlSessionFactory(工廠)
- SqlSessionFactory 一旦被創(chuàng)建就應該在應用的運行期間一直存在,沒有任何理由丟棄它或重新創(chuàng)建另一個實例
- 數(shù)據(jù)庫連接池
- SqlSessionFactory 的最佳作用域是應用作用域
- 最簡單的就是使用單例模式或者靜態(tài)單例模式
SqlSession(會話)
- 連接到SqlSessionFactory(連接池)的一個請求
- SqlSession 的實例不是線程安全的,因此是不能被共享的,所以它的最佳的作用域是請求或方法作用域。
- 使用完需要趕緊關閉,否則資源被占用 SqlSession.close()
到此這篇關于Spring數(shù)據(jù)庫連接池實現(xiàn)原理深入刨析的文章就介紹到這了,更多相關Spring數(shù)據(jù)庫連接池內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot?JavaMailSender發(fā)送郵件功能(實例詳解)
JavaMailSender是Spring提供的,非常好用的,實現(xiàn)郵件發(fā)送的接口 ,這篇文章主要介紹了SpringBoot?JavaMailSender發(fā)送郵件功能,需要的朋友可以參考下2024-03-03
深入淺析Java中Static Class及靜態(tài)內部類和非靜態(tài)內部類的不同
上次有朋友問我,java中的類可以是static嗎?我給他肯定的回答是可以的,在java中我們可以有靜態(tài)實例變量、靜態(tài)方法、靜態(tài)塊。當然類也可以是靜態(tài)的,下面小編整理了些關于java中的static class相關資料分享在腳本之家平臺供大家參考2015-11-11
詳解springboot接口如何優(yōu)雅的接收時間類型參數(shù)
這篇文章主要為大家詳細介紹了springboot的接口如何優(yōu)雅的接收時間類型參數(shù),文中為大家整理了三種常見的方法,希望對大家有一定的幫助2023-09-09
springboot內置tomcat調優(yōu)并發(fā)線程數(shù)解析
這篇文章主要介紹了springboot內置tomcat調優(yōu)并發(fā)線程數(shù)解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12
java多態(tài)實現(xiàn)電子寵物系統(tǒng)
這篇文章主要為大家詳細介紹了java多態(tài)實現(xiàn)電子寵物系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02

