1. 初始MyBatis ,詳細步驟運行第一個MyBatis程序,同時對應步驟MyBatis底層剖析
文章目錄
- 1. 初始MyBatis ,詳細步驟運行第一個MyBatis程序,同時對應步驟MyBatis底層剖析
- 每博一文案
- 2. 前沿知識
- 2.1 框架(framework)
- 2.2 三層架構
- 2.3 分析 JDBC 的缺點
- 3. 初始了解MyBatis
- 4. MyBatis第一個入門程序
- 4.1 MyBatis下載
- 4.2 MyBatis入門程序開發步驟
- 4.3 MyBatis 的第一個入門程序的細節問題
- 5. 關于MyBatis核心配置文件的名字和路徑詳解
- 6. 關于 mybatis 的事務管理機制(深度剖析)
- 7. MyBatis第一個比較完整的代碼寫法
- 8. MyBatis 引入日志框架
- 8.1 使用 MyBatis 自帶的日志框架
- 8.2 引入 logback 日志框架
- 9. 總結:
- 10. 最后:
每博一文案
才華果然比金錢更耀眼
2. 前沿知識
2.1 框架(framework)
Java當中常見的框架:
- SSM三大框架:Spring + SpringMVC + MyBatis
- SpringBoot
- SpringCloud
- …
框架其實就是對通用代碼的封裝,被提前寫好的一大堆接口和類(供你使用),我們可以在做項目的時候直接引入這些接口和類(引入框架),基于這些現有的接口和類進行開發,可以大大提高開發效率。
框架一般都是以jar
包的形式存在。(jar 包中有 class 文件以及各種配置文件等。)
SSM三大框架的學習順序:MyBatis,Spring,SpringMVC 。因為 MyBatis 框架和后面兩個 Spring,SpringMVC 比較的獨立開來了,可以先學。
關于Spring 框架的內容,大家感興趣的可以移步至:?????? Spring_ChinaRainbowSea的博客-CSDN博客
2.2 三層架構
- 表示層(直接跟前端進行交互的,一是接受前端 AJAX 請求,二是返回 JSON 數據給前端)
- 業務邏輯層:一是處理表現層轉發過來的前端請求(也就是具體的業務),二是將從持久層獲取的數據返回到表示層。
- 數據訪問層:直接操作數據庫完成CRUD,并獲得數據返回到上一層(也就是業務邏輯層)
- Java持久層框架:
關于持久層的框架有如下這些:
- MyBatis
- Hibernate(實現了JPA規范)
- jOOQ
- Guzz
- Spring Data(實現了JPA 規范)
- ActiveJDBC
- …
更多關于三層架構的內容,大家可以移步至:?????? MVC 三層架構案例詳細講解_mvc三層架構-CSDN博客
2.3 分析 JDBC 的缺點
我們先觀察,分析如下代碼的
示例1:
// ......
// sql語句寫死在java程序中
String sql = "insert into t_user(id,idCard,username,password,birth,gender,email,city,street,zipcode,phone,grade) values(?,?,?,?,?,?,?,?,?,?,?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
// 繁瑣的賦值:思考一下,這種有規律的代碼能不能通過反射機制來做自動化。
ps.setString(1, "1");
ps.setString(2, "123456789");
ps.setString(3, "zhangsan");
ps.setString(4, "123456");
ps.setString(5, "1980-10-11");
ps.setString(6, "男");
ps.setString(7, "zhangsan@126.com");
ps.setString(8, "北京");
ps.setString(9, "大興區涼水河二街");
ps.setString(10, "1000000");
ps.setString(11, "16398574152");
ps.setString(12, "A");
// 執行SQL
int count = ps.executeUpdate();
// ......
示例2:
// ......
// sql語句寫死在java程序中
String sql = "select id,idCard,username,password,birth,gender,email,city,street,zipcode,phone,grade from t_user";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
List<User> userList = new ArrayList<>();
// 思考以下循環中的所有代碼是否可以使用反射進行自動化封裝。
while(rs.next()){// 獲取數據String id = rs.getString("id");String idCard = rs.getString("idCard");String username = rs.getString("username");String password = rs.getString("password");String birth = rs.getString("birth");String gender = rs.getString("gender");String email = rs.getString("email");String city = rs.getString("city");String street = rs.getString("street");String zipcode = rs.getString("zipcode");String phone = rs.getString("phone");String grade = rs.getString("grade");// 創建對象User user = new User();// 給對象屬性賦值user.setId(id);user.setIdCard(idCard);user.setUsername(username);user.setPassword(password);user.setBirth(birth);user.setGender(gender);user.setEmail(email);user.setCity(city);user.setStreet(street);user.setZipcode(zipcode);user.setPhone(phone);user.setGrade(grade);// 添加到集合userList.add(user);
}
// ......
JDBC的不足點:
SQL語句寫牢在了Java程序當中了,不靈活,改SQL的話,就要改Java代碼,違背了開閉原則OCP。
給
?
占位符傳值是繁瑣的,不能自動化將結果集封裝成Java對象也是比較繁瑣的,不能自動化
關于這些自動化的問題,以及OCP開閉原則,運用下面我們正在學習的MyBatis 可以得到一個很好的解決方案。
關于JDBC的更多詳細內容,大家可以移步至:?????? JDBC_ChinaRainbowSea的博客-CSDN博客
3. 初始了解MyBatis
MyBatis 本質上就是對JDBC的封裝,通過MyBatis完成CRUD。
MyBatis 在三層架構中負責持久層,屬于持久層框架。
MyBatis的發展歷程:這里【引用百度百科】
- MyBatis本是apache的一個開源項目iBatis,2010年這個項目由apache software foundation遷移到了[google code](https://baike.baidu.com/item/google code/2346604?fromModule=lemma_inlink),并且改名為MyBatis。2013年11月遷移到Github。
- iBATIS一詞來源于“internet”和“abatis”的組合,是一個基于Java的持久層框架。iBATIS提供的持久層框架包括SQL Maps和Data Access Objects(DAOs)。
- 當前,最新版本是MyBatis 3.5.13,其發布時間是2023年03月11日。
打開MyBatis 代碼可以看到它的包結構中包含:ibatis
ORM :對象關系映射。
O (object) :Java虛擬機中的Java對象。
R(Relational):關系型數據庫
M(Mapping):將Java虛擬機中的Java對象映射到數據庫表中一行記錄,或是將數據庫表中一行記錄映射成Java虛擬機中的一個Java對象。
ORM示圖:
MyBatis 框架就是一個ORM框架。
MyBatis可以干啥?
java 對象 < ------ > 數據庫表中的一條記錄
像User 這樣在圖中,有特殊的稱呼: 有的人把它叫做:pojo(普通Java類) 有的叫做: JavaBean (咖啡豆) 有的叫做: domain(領域模型)
MyBatis 是一個半自動化的ORM,因為MyBatis 框架中SQL語句是需要程序員自己寫的。
Hibernate 框架是一個全自動化的ORM 使用Hibenrnate 框架的時候,不需要程序員手動編寫SQL語句,SQL語句可以自動生成,所以Hibernate 是一個完全的全自動化的ORM框架。
這里我們的主題是 MyBatis 。
MyBatis 框架特點:
- 支持定制化SQL,存儲過程,基本映射以及高級映射
- 避免了幾乎所有的 JDBC代碼中手動設置參數以及獲取結果集。
- 支持XML 開發,也支持注解開發。【為了保證 SQL 語句的靈活,所有MyBatis 大部分采用 XML方式開發。】
- 將接口和 Java 的 POJOs(Plain Ordinary Java Object ,簡單普通的Java對象)映射成數據庫中的記錄
- 體積小,好學,兩個jar 包,兩個 XML 配置文件
- 完全做到 SQL 解耦合
- 提供了基本映射標簽
- 提供了高級映射標簽
- 提供了XML標簽,支持動態SQL的編寫。
4. MyBatis第一個入門程序
4.1 MyBatis下載
- 從github上下載,地址:https://github.com/mybatis/mybatis-3
將框架以及框架的源碼都下載下來,下載框架后解壓,打開mybatis目錄
-
通過以上解壓可以看到,框架一般都是以jar包的形式存在。我們的mybatis課程使用 maven,所以這個jar我們不需要。
-
官方手冊需要。但是,這個官方文檔是英文的,對應英文不好的朋友,大家可以來的這個網站:https://mybatis.net.cn/ 是一個 mybatis 的中文網站。
-
4.2 MyBatis入門程序開發步驟
首先我們先準備好數據庫信息
準備數據庫表:汽車表t_car,字段包括:
id:主鍵(自增)【bigint】
car_num:汽車編號【varchar】
brand:品牌【varchar】
guide_price:廠家指導價【decimal類型,專門為財務數據準備的類型】
produce_time:生產時間【char,年月日即可,10個長度,‘2022-10-11’】
car_type:汽車類型(燃油車、電車、氫能源)【varchar】
DROP TABLE IF EXISTS `t_car`;
CREATE TABLE `t_car` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主鍵,和業務沒有關系,自增',`car_num` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '汽車編號',`brand` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '汽車品牌',`guide_price` decimal(10, 2) NULL DEFAULT NULL COMMENT '廠商指導價格',`produce_time` char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '生產日期',`car_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '汽車類型,燃油車,氫能源',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 33 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;
INSERT INTO `t_car` VALUES (1, '1001', '寶馬520Li', 10.00, '2020-10-11', '燃油車');
INSERT INTO `t_car` VALUES (2, '1002', '奔馳E300L', 55.00, '2020-11-11', '新能源');
INSERT INTO `t_car` VALUES (5, '1003', '豐田霸道', 30.00, '2000-10-11', '燃油車');
創建Project:建議創建Empty Project,設置Java版本以及編譯版本等。
創建Module:普通的Maven Java模塊
第一步:通過maven 在 pom.xml
文件當中引入相關依賴。
mybatis依賴 ,mysql依賴
<!--mybatis核心依賴-->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.10</version>
</dependency><!--mysql驅動依賴-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version>
</dependency>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.ranbowsea</groupId><artifactId>mybatis-001-introduction</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><!--mybatis核心依賴--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.10</version></dependency><!--mysql驅動依賴--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency></dependencies></project>
第二步:在 resources
根(類)目錄下新建 mybatis-config.xml
(文件名隨意)配置文件(可以參考mybatis手冊拷貝 (https://mybatis.net.cn/getting-started.html))
注意:
- 第一,這個文件名不是必須叫 mybatis-config.xml,可以用其他的名字,只是大家都采用這個名字。
- 這個文件存放的位置也不是固定的,可以隨意,但一般情況下,會放到類的根路徑下
關于這兩點的注意事項,該文章的后面,會詳細說明。請繼續看下去。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><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/powernode"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><mappers><!--sql映射文件創建好之后,需要將該文件路徑配置到這里--><mapper resource=""/></mappers>
</configuration>
第三步:編寫XxxMapper.xml 文件
在這個配置文件當編寫SQL語句。
這個文件名也不是固定的,放的位置也不是固定的,我們這里給它起個名字,叫做:CarMapper.xml (mapper 英文單詞是“映射”的意思),把它暫時放到類的根路徑下。
在resources根目錄下新建CarMapper.xml配置文件(可以參考mybatis手冊拷貝)
同時我們在其中編寫一條SQL語句,一條insert 插入的SQL語句。
注意編寫的是 insert 插入的SQL語句所以,在該 xml 文件中用,<insert> 標簽進行定義編寫。如下:
而在<insert> 標簽當中,需要定義一個 id 屬性的值,該
insert語句,id是這個條SQL語句的唯一標識,這個id就代表了這條SQL語句
<!-- insert語句,id是這個條SQL語句的唯一標識,這個id就代表了這條SQL語句 --><insert id="insertCar">insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)values (null,'1003','豐田霸道',30.0,'2000-10-11','燃油車')</insert> // 因為我們的 id 是主鍵,自增的,所以可以不賦值。為 null ,讓其進行一個自增的效果。
因為我們的 id 是主鍵,自增的,所以可以不賦值。為 null ,讓其進行一個自增的效果。
注意1:sql語句最后結尾可以不寫“;”
注意2:CarMapper.xml文件的名字不是固定的。可以使用其它名字。
注意3:CarMapper.xml文件的位置也是隨意的。這里選擇放在resources根下,相當于放到了類的根路徑下。
注意4:將CarMapper.xml文件路徑配置到mybatis-config.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace先隨意寫一個-->
<mapper namespace="fas"><!-- insert語句,id是這個條SQL語句的唯一標識,這個id就代表了這條SQL語句 --><insert id="insertCar">insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)values (null,'1003','豐田霸道',30.0,'2000-10-11','燃油車')</insert>
</mapper>
第四步: 在mybatis-config.xml 文件中指定XxxMapper.xml 文件的路徑
就是將我們上面配置的 XxxMapper.xml(這里是 CarMapper.xml)
的SQL語句的映射文件創建好,將該文件所在位置的路徑,填入到 <mapper resource="xxx">
當中,讓MyBatis 框架可以順利的找到它,并執行其中的SQL語句。注意:resource 屬性會自動從類的根路徑下開始查找資源。
<mapper resource="CarMapper.xml">
注意:resource 屬性會自動從類的根路徑下開始查找資源。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><environments default="development"><environment id="development">
<!-- MANAGED 沒有用第三框架管理的話,都是會被提交的,沒有事務上的管理了。--><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis"/><property name="username" value="root"/><property name="password" value="MySQL123"/></dataSource></environment></environments><mappers><!--sql映射文件創建好之后,需要將該文件路徑配置到這里-->
<!-- 執行XxxMapper.xml 文件的路徑-->
<!-- resource 屬性自動會從類的根路徑下開始查找資源--><mapper resource="CarMapper.xml"/></mappers></configuration>
第五步: 編寫MyBatis 測試程序(使用MyBatis的類庫,編寫myBatis 程序,該數據庫,做增刪改查就行了)
首先我們需要知道,在MyBatis 當中,負責執行SQL語句的是哪個對象,同時又該如何獲取到該對象。
負責執行 SQL語句的對象是: SqlSession
SqlSession 是專門來執行 SQL語句的,是一個Java程序和數據庫之間的一次會話
想要獲取到 SqlSession 對象,就需要先獲取SqlSessionFactory 對象,通過SqlSessionFactory 工廠的openSession( ) 方法,來生產 SqlSession 對象。
那怎么湖獲取SqlSessionFactory 對象
通過SqlSessionFactoryBuilder 對象的 build( ) 方法,來獲取一個SqlSessionFactory 對象。
總結:
MyBatis的核心對象包括:
SqlSessionFactoryBuilder
SqlSessionFactory
SqlSessionSqlSessionFactoryBuilder–>SqlSessionFactory–>SqlSession
注意事項:
int count = sqlSession.insert("insertCar"); // 這個"insertCar"必須是sql的id
該insert(id) 就是,我們上面 CarMapper.xml SQL映射文件當中編寫的 SQL 語句(這里是 <insert> 標簽當中的 id 的屬性值,保持一致)
同時需要:
執行 sqlSession.commit(); 提交數據給數據庫(和JDBC是一樣的); 提交(mybatis默認采用的事務管理器是JDBC,默認是不提交的,需要手動提交。)
以及執行: sqlSession.close(); 關閉資源,注意:僅僅是關閉資源,并不會提交數據的。
// 5. 提交(mybatis默認采用的事務管理器是JDBC,默認是不提交的,需要手動提交。) sqlSession.commit(); // 6. 關閉資源(只關閉是不會提交的) sqlSession.close();
完整執行代碼:
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.FileInputStream;
import java.io.IOException;
import java.io.InputStream;public class MyBatisIntroductionTest {public static void main(String[] args) {// 1. 創建SqlSessionFactoryBuilder對象SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();// 2. 創建SqlSessionFactory對象InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);// 3. 創建SqlSession對象SqlSession sqlSession = sqlSessionFactory.openSession();// 4. 執行sqlint count = sqlSession.insert("insertCar"); // 這個"insertCar"必須是sql的idSystem.out.println("插入幾條數據:" + count);// 5. 提交(mybatis默認采用的事務管理器是JDBC,默認是不提交的,需要手動提交。)sqlSession.commit();// 6. 關閉資源(只關閉是不會提交的)sqlSession.close();}
}
運行結果:
MyBatis 第一個入門程序小總結:
第一: 在MyBatis中一定是有一個很重要的對象,這個對象是:SqlSessionFactory對象
第二: SqlSessionFactory 對象的創建需要 xml
xml 是什么?它是一個配置文件
MyBatis中有兩個主要的配置文件:
- mybatis-config.xml ,這是核心配置文件,主要配置連接數據庫的信息等(一般是第一個數據庫一個),同樣的與之對應的通過
mybatis-config.xml
的配置文件創建的對象 SqlSessionFactoryBuilder,SqlSessionFactory 也是一個數據庫一個對象 。- XxxMapper.xml ,這個是專門用來編寫SQL語句的配置文件(一個數據表一個)。
t_user 表,一般會對應一個UserMapper.xml
t_student 表,一般會對應一個StudentMapper.xml
4.3 MyBatis 的第一個入門程序的細節問題
- 在MyBatis 中的SQ語句的結尾“;” 可以省略的。
- 在 MyBatis 當中的 SQL語句錯誤的,異常信息是:
java.sql.SQLSyntaxErrorException
該異常表示是你的SQL語句寫的不對,SQL語法可能存在問題。
- 在MyBatis 當中的工具類: Resource.getResourceAsStream( ) 方法。
小技巧:以后凡是遇到 resource 這個單詞,大部分情況下,這種加載資源的方式就是從
(resource)
類路徑下開始檢索加載的。例如: 下面三種獲取 IO流文件的,檢索方式都是從類路徑下開始的。
InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml"); InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml"); // 使用類加載器
采用從 (resource)類路徑 加載文件的優點:
采用這種方式,從類的路徑當種加載資源,項目的移植性很強,項目從Windwos移植到Linux,沒有路徑上的問題
而下面這個是:從系統的絕對路徑開始加載的
InputStream stream = new FileInputStream("E:\\mybatis-config.xml");
采用系統的絕對路徑加載文件資源的缺點:
可移植性差,程序不夠健壯,可能移植到其他的操作系統當中,導致以上路徑無效,比如Linux,因為Linux系統是沒有所謂的D盤,C盤之類的說法。所以想要移植到Linux當中運行的話,還需要修改Java代碼才行。這樣就違背了OCP原則了。
5. 關于MyBatis核心配置文件的名字和路徑詳解
MyBatis 的核心配置文件就是,我們上述的名為 mybatis-config.xml
的配置文件。
已經驗證過了,mybatis 核心配置文件的名字,不一定是:mybatis-config.xml 。mybatis 核心配置文件存放的路徑,也不一定是類的根路徑,可以放到其他的位置,但是為了項目的移植性。健壯性,最好將這個配置文件放到類路徑下面。
同理的對應的 SQL 映射文件 XxxMapper.xml 文件的路徑也可以不放在根(類)路徑下,不過如果 SQL 映射文件 XxxMapper.xml 文件是根據 系統的絕對路徑 來的話,需要用 <url> 標簽。如下:
重點:注意的是,無論是 MyBatis 的核心配置文件,還是對應的 SQL 映射文件 XxxMapper.xml 文件,如果文件含義目錄的話,一定要帶上目錄才行如下:
源碼解析:MyBatis 工具類的:InputStream is = Resources.getResourceAsStream(“mybatis-config.xml”) 的底層調用的機制。
> InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml")
> ClassLoader.getSystemClassLoader() 獲取系統的類加載器。
> 系統類加載器有一個方法叫做:getResourceAsSteam
> 它就是從類路徑當中加載資源的
> 通過源代碼分析發現:
> InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
> 底層的源代碼其實現就是:
> InputStream is = ClasLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml");
>
6. 關于 mybatis 的事務管理機制(深度剖析)
關于 mybatis 的事務管理機制:
在mybatis-config.xml 文件中,可以通過以下的配置進行 mybatis 的事務處理。
通過:**<transactionManager type=“JDBC”> ** 標簽進行設置即可。
type 的屬性值包括兩個:
- JDBC (jdbc)
- MANGED(managed)
type 后面的值,只有以上兩個值可以選擇,不區分大小寫。
在mybatis 中提供了兩種事務管理機制。
- 第一種 JDBC事務管理器
MyBatis 框架自己管理事務,自己采用原生的JDBC 代碼去管理事務
> conn.setAutoCommit(false);開啟事務,false 是默認的,可以不用寫
> ...業務處理...
> conn.commit(); 手動提交事務
使用JDBC事務管理器的話,底層創建的事務管理器對象,jdbcTransaction對象。
如果你編寫的代碼是下面的代碼:SqlSession sqlSession = sqlSessionFactory.openSession(true);表示沒有開啟事務,因為這種方式壓根不會執行,com.setAutoCommit(false)在JDBC事務中,沒有執行com.setAutoCommit(false);那么autoCommit就是true.如果autoCommit 是 true ,就表示沒有開啟事務,只要執行任意一條DML語句就提交了一次
我們可以進行一個 Debug 調試,進行一個檢查
這里我們用默認的 false ,也可以不填,都是 false
SqlSession sqlSession = sqlSessionFactory.openSession();SqlSession sqlSession = sqlSessionFactory.openSession(false);
下面我們設置為:true
在 JDBC事務管理器 下,SqlSession sqlSession = sqlSessionFactory.openSession( 不填,或者 false); 表示開啟事務了(需要自己手動提交,sqlSession.commit()😉,填 true 表示關閉了事務,自動就會提交了
- 第二種 MANAGED 是事務管理器
在 mybatis 不再負責事務的管理了,事務管理交給其他容器來負責,例如:Spring
<!-- MANAGED 沒有用第三框架管理的話,都是會被提交的,沒有事務上的管理了。--><transactionManager type="MANAGED"/>
MyBatis 說,我不管事務了(會自動提交數據給數據庫),你來負責吧(Spring)
如果對于我們當前的單純的只有 MyBatis 的情況下,如果配置為:MANAGED ,那么事務這塊是沒人管的,沒有人管理事務標識,事務壓根沒有開啟,后面我們可以配合使用Spring 進行事務上的管理。
關于 MyBatis 配合Spring 開啟事務的詳細內容,大家可以移步至:?????? Spring6 對 集成MyBatis 開發運用(附有詳細的操作步驟)-CSDN博客
7. MyBatis第一個比較完整的代碼寫法
resources 的配置文件下的信息。
CarMapper.xml SQL 語句的映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace先隨意寫一個-->
<mapper namespace="fas"><!-- insert語句,id是這個條SQL語句的唯一標識,這個id就代表了這條SQL語句 --><insert id="insertCar">insert into t_car(id,car_num,brand,guide_price,produce_time,car_type)values (null,'1003','豐田霸道',30.0,'2000-10-11','燃油車');</insert>
</mapper>
mybatis-config.xml 的MyBatis 的核心配置文件。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 開啟mybatis 對標準日志的實現-->
<!-- 如果導入的第三方框架的日志,沒有下面這個 settings 也是可以的-->
<!-- <settings>-->
<!-- <setting name="logImpl" value="STDOUT_LOGGING"/>-->
<!-- </settings>--><environments default="development"><environment id="development">
<!-- MANAGED 沒有用第三框架管理的話,都是會被提交的,沒有事務上的管理了。--><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis"/><property name="username" value="root"/><property name="password" value="MySQL123"/></dataSource></environment></environments><mappers><!--sql映射文件創建好之后,需要將該文件路徑配置到這里-->
<!-- 執行XxxMapper.xml 文件的路徑-->
<!-- resource 屬性自動會從類的根路徑下開始查找資源-->
<!-- <mapper resource="CarMapper.xml"/>--><mapper resource="com/CarMapper2.xml"/><!-- url屬性: 從絕對路徑當中加載資源。-->
<!-- 語法格式:file:///絕對路徑-->
<!-- <mapper url="file:///e:/CarMapper.xml"></mapper>--></mappers></configuration>
運行測試程序:
package com.rainbowsea.mybatis.test;import com.ranbowsea.mybatis.utils.SqlSessionUtil;
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 org.junit.Test;import java.io.IOException;public class MyBatisCompleteTest {public static void main(String[] args) {// 獲取到SqlSessionFactoryBuilder 對象SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSession sqlSession = null;try {// 獲取到SqlSessionFactoryBuilder 一個數據庫對應一個 SqlSessionFactoryBuilderSqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsReader("mybatis-config.xml"));// 獲取到SqlSession對象sqlSession = sqlSessionFactory.openSession();sqlSession.insert("insertCar");// 對應 執行SQL語句對應的數據表的 XxxMapper.xml當中,對應SQL語句的id// 執行到這里,提交事務,終止事務sqlSession.commit();} catch (IOException e) {if(sqlSession != null) { // 上面可能 sqlSession 還是為空// 回滾事務sqlSession.rollback();}throw new RuntimeException(e);} finally {if(sqlSession != null) {// 關閉會話sqlSession.close();}}}}
8. MyBatis 引入日志框架
8.1 使用 MyBatis 自帶的日志框架
引入日志框架的目的:是為了看清楚MyBatis執行的具體的 SQL語句,以及賦值內容。
啟動MyBatis 自帶的標準日志組件,只需要在mybatis-config.xml
MyBatis 的核心配置文件中添加配置文件【可參考mybatis 手冊https://mybatis.net.cn/logging.html】
關于mybatis 集成日志組件,讓我們調試起來更加方便。
mybatis常見的集成的日志組件有哪些呢?
SLF4J(沙拉風)
LOG4J
LOG$J2
STDOUT_LOGGING
…
注意:log4j log4j2 logback都是同一個作者開發的。
其中STDOUT_LOGGING 是標準日志,mybatis已經實現了這種標準日志,mybatis框架本身已經實現了這種
標準。只要開啟即可,怎么開啟呢?在mybatis-config.xml文件中使用settings標簽進行配置開啟。
<settings><setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
注意:
這個標簽在編寫的時候要注意,它必須在 environments 標簽之前(不然會報錯的),注意順序,當然,不需要記憶這個順序。
因為有dtd文件進行約束呢。我們只要參考did約束即可
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 開啟mybatis 對標準日志的實現--><settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings><environments default="development"><environment id="development">
<!-- MANAGED 沒有用第三框架管理的話,都是會被提交的,沒有事務上的管理了。--><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis"/><property name="username" value="root"/><property name="password" value="MySQL123"/></dataSource></environment></environments><mappers><!--sql映射文件創建好之后,需要將該文件路徑配置到這里-->
<!-- 執行XxxMapper.xml 文件的路徑-->
<!-- resource 屬性自動會從類的根路徑下開始查找資源-->
<!-- <mapper resource="CarMapper.xml"/>--><mapper resource="com/CarMapper2.xml"/><!-- url屬性: 從絕對路徑當中加載資源。-->
<!-- 語法格式:file:///絕對路徑-->
<!-- <mapper url="file:///e:/CarMapper.xml"></mapper>--></mappers></configuration>
運行測試:
8.2 引入 logback 日志框架
上述的MyBatis 自帶的日志框架,這種實現也是可以的,可以看到一些信息,比如:連接對象什么時候創建,什么時候關閉,sql語句是怎樣的
但是沒有詳細的日期,線程名字,等,如果你想使用更加豐富的配置,可以集成第三方Log組件。
同時配置也不夠靈活,我們可以集成其他的日志組件,例如:log4j,logback等。
- logback是目前日志框架中性能較好的,較流行的,所以我們選它。
- 引入logback的步驟:
logback 日志框架實現了slf4j標準(沙拉風,日志門面,日志標準)
第一步: 引入logback的依賴
我們需要在項目的 pom.xml
配置文件當中,引入 logbakc 的依賴,通過 maven 進行導入。
<!-- 引入 logback的依賴,這個日志框架實現了slf4j 規范--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.11</version></dependency>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.ranbowsea</groupId><artifactId>mybatis-001-introduction</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><!--mybatis核心依賴--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.10</version></dependency><!--mysql驅動依賴--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency><!-- junit 依賴--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><!-- 引入 logback的依賴,這個日志框架實現了slf4j 規范--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.11</version></dependency></dependencies></project>
第二步:如logback所必須的 xml 配置文件
注意:這個配置文件的名字必須叫做:logback.xml
或者 logback-test.xml
不能是其他的名字
并且這個配置文件必須放到類的根路徑下,不能是其他位置。
<?xml version="1.0" encoding="UTF-8"?><configuration debug="false"><!-- 控制臺輸出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日志消息,%n是換行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder></appender><!-- 按照每天生成日志文件 --><appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--日志文件輸出的文件名--><FileNamePattern>${LOG_HOME}/TestWeb.log.%d{yyyy-MM-dd}.log</FileNamePattern><!--日志文件保留天數--><MaxHistory>30</MaxHistory></rollingPolicy><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日志消息,%n是換行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder><!--日志文件最大的大小--><triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"><MaxFileSize>100MB</MaxFileSize></triggeringPolicy></appender><!--mybatis log configure--><logger name="com.apache.ibatis" level="TRACE"/><logger name="java.sql.Connection" level="DEBUG"/><logger name="java.sql.Statement" level="DEBUG"/><logger name="java.sql.PreparedStatement" level="DEBUG"/><!-- 日志輸出級別,logback日志級別包括五個:TRACE < DEBUG < INFO < WARN < ERROR --><root level="DEBUG"><appender-ref ref="STDOUT"/><appender-ref ref="FILE"/></root></configuration>
<?xml version="1.0" encoding="UTF-8"?><configuration debug="false"><!-- 控制臺輸出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日志消息,%n是換行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder></appender><!--mybatis log configure--><logger name="com.apache.ibatis" level="TRACE"/><logger name="java.sql.Connection" level="DEBUG"/><logger name="java.sql.Statement" level="DEBUG"/><logger name="java.sql.PreparedStatement" level="DEBUG"/><!-- 日志輸出級別,logback日志級別包括五個:TRACE < DEBUG < INFO < WARN < ERROR --><root level="ERROR"><appender-ref ref="STDOUT"/><appender-ref ref="FILE"/></root></configuration>
配置好以后,我們運行看看。
package com.rainbowsea.mybatis.test;import com.ranbowsea.mybatis.utils.SqlSessionUtil;
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 org.junit.Test;import java.io.IOException;public class MyBatisCompleteTest {public static void main(String[] args) {// 獲取到SqlSessionFactoryBuilder 對象SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSession sqlSession = null;try {// 獲取到SqlSessionFactoryBuilder 一個數據庫對應一個 SqlSessionFactoryBuilderSqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsReader("mybatis-config.xml"));// 獲取到SqlSession對象sqlSession = sqlSessionFactory.openSession();sqlSession.insert("insertCar");// 對應 執行SQL語句對應的數據表的 XxxMapper.xml當中,對應SQL語句的id// 執行到這里,提交事務,終止事務sqlSession.commit();} catch (IOException e) {if(sqlSession != null) { // 上面可能 sqlSession 還是為空// 回滾事務sqlSession.rollback();}throw new RuntimeException(e);} finally {if(sqlSession != null) {// 關閉會話sqlSession.close();}}}}
9. 總結:
MyBatis 本質上就是對JDBC的封裝,通過MyBatis完成CRUD。MyBatis 在三層架構中負責持久層,屬于持久層框架。
MyBatis 的包目錄,路徑是 ibatis 。不是 mybatis 。這一點需要注意清楚明白。
mybatis 核心配置文件的名字,不一定是:mybatis-config.xml 。mybatis 核心配置文件存放的路徑,也不一定是類的根路徑,可以放到其他的位置,但是為了項目的移植性。健壯性,最好將這個配置文件放到類路徑下面。
MyBatis 的SQL 映射文件XxxMapper.xml 和MyBatis 的核心配置文件, mybatis-config.xml 都盡量放到類(resources) 根路徑下 ,為了項目的移植性。健壯性,最好將這個配置文件放到類路徑下面。
小技巧:以后凡是遇到 resource 這個單詞,大部分情況下,這種加載資源的方式就是從
(resource)
類路徑下開始檢索加載的。例如: 下面三種獲取 IO流文件的,檢索方式都是從類路徑下開始的。
InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("mybatis-config.xml"); InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("mybatis-config.xml"); // 使用類加載器
在mybatis 中提供了兩種事務管理機制
第一種 JDBC事務管理器
MyBatis 框架自己管理事務,自己采用原生的JDBC 代碼去管理事務
> conn.setAutoCommit(false);開啟事務,false 是默認的,可以不用寫 > ...業務處理... > conn.commit(); 手動提交事務
使用JDBC事務管理器的話,底層創建的事務管理器對象,jdbcTransaction對象。
在 JDBC事務管理器 下,SqlSession sqlSession = sqlSessionFactory.openSession( 不填,或者 false); 表示開啟事務了(需要自己手動提交,sqlSession.commit()😉,填 true 表示關閉了事務,自動就會提交了
第二種 MANAGED 是事務管理器
在 mybatis 不再負責事務的管理了,事務管理交給其他容器來負責,例如:Spring 。
如果對于我們當前的單純的只有 MyBatis 的情況下,如果配置為:MANAGED ,那么事務這塊是沒人管的,沒有人管理事務標識,事務壓根沒有開啟,后面我們可以配合使用Spring 進行事務上的管理。
引入日志框架的目的:是為了看清楚MyBatis執行的具體的 SQL語句,以及賦值內容。
啟動MyBatis 自帶的標準日志組件,只需要在
mybatis-config.xml
MyBatis 的核心配置文件中添加配置文件<settings><setting name="logImpl" value="STDOUT_LOGGING" /> </settings>
setting 這個標簽在編寫的時候要注意,它必須在 environments 標簽之前(不然會報錯的),注意順序,當然,不需要記憶這個順序。
引入 logback 日志框架。導入的依賴
<!-- 引入 logback的依賴,這個日志框架實現了slf4j 規范--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.11</version></dependency>
如logback所必須的 xml 配置文件**
注意:這個配置文件的名字必須叫做:
logback.xml
或者logback-test.xml
不能是其他的名字
并且這個配置文件必須放到類的根路徑下,不能是其他位置。
10. 最后:
“在這個最后的篇章中,我要表達我對每一位讀者的感激之情。你們的關注和回復是我創作的動力源泉,我從你們身上吸取了無盡的靈感與勇氣。我會將你們的鼓勵留在心底,繼續在其他的領域奮斗。感謝你們,我們總會在某個時刻再次相遇。”