首頁 > 科技

這可能是全網最詳細的MyBatis手冊,建議收藏

2021-06-29 09:15:54

1、簡介

1.1 什麼是Mybatis

MyBatis 是一款優秀的持久層框架;

它支援自定義 SQL、儲存過程以及高階對映。MyBatis 免除了幾乎所有的 JDBC 程式碼以及設定參數和獲取結果集的工作。MyBatis 可以通過簡單的 XML 或註解來配置和對映原始類型、介面和 Java POJO(Plain Old Java Objects,普通老式 Java 物件)為資料庫中的記錄。

1.2 持久化

資料持久化

持久化就是將程式的資料在持久狀態和瞬時狀態轉化的過程記憶體:斷電即失資料庫(Jdbc),io檔案持久化。為什麼要持久化?

有一些物件,不能讓他丟掉記憶體太貴1.3 持久層

Dao層、Service層、Controller層

完成持久化工作的程式碼塊

層界限十分明顯

1.4 為什麼需要MyBatis

幫助程式設計師將資料存入到資料庫中

方便

傳統的JDBC程式碼太複雜了,簡化,框架,自動化

不用MyBatis也可以,技術沒有高低之分

優點:

簡單易學靈活sql和程式碼的分離,提高了可維護性。提供對映標籤,支援物件與資料庫的orm欄位關係對映提供物件關係對映標籤,支援物件關係組建維護提供xml標籤,支援編寫動態sql2、第一個Mybatis程式

思路:搭建環境 --> 匯入MyBatis --> 編寫程式碼 --> 測試

2.1 搭建環境

新建項目

創建一個普通的maven項目刪除src目錄 (就可以把此工程當做父工程了,然後創建子工程)匯入maven依賴

4.創建一個Module

2.2 創建一個模組

編寫mybatis的核心配置檔案

編寫mybatis工具類

2.3 編寫程式碼

實體類Dao介面public interface UserDao {

public List<User> getUserList();

}

介面實現類 (由原來的UserDaoImpl轉變為一個Mapper配置檔案)

測試

注意點:

org.apache.ibatis.binding.BindingException: Type interface com.kuang.dao.UserDao is not known to the MapperRegistry.

MapperRegistry是什麼?

核心配置檔案中註冊mappers

junit測試

可能會遇到的問題:

配置檔案沒有註冊

繫結介面錯誤

方法名不對

返回類型不對

Maven匯出資源問題

3、CURD

1. namespace

namespace中的包名要和Dao/Mapper介面的包名一致

2. select

選擇,查詢語句;

id:就是對應的namespace中的方法名;resultType : Sql語句執行的返回值;parameterType : 參數類型;編寫介面

編寫對應的mapper中的sql語句

測試

注意:增刪改查一定要提交事務:

sqlSession.commit();

1

3. Insert

4. update

5. Delete

6. 萬能Map

假設,我們的實體類,或者資料庫中的表,欄位或者參數過多,我們應該考慮使用Map!

UserMapper介面//用萬能Map插入使用者

public void addUser2(Map<String,Object> map);

UserMapper.xml<!--物件中的屬性可以直接取出來 傳遞map的key-->

<insert id="addUser2" parameterType="map">

insert into user (id,name,password) values (#{userid},#{username},#{userpassword})

</insert>

測試

Map傳遞參數,直接在sql中取出key即可! 【parameter=「map」】

物件傳遞參數,直接在sql中取出物件的屬性即可! 【parameter=「Object」】

只有一個基本類型參數的情況下,可以直接在sql中取到

多個參數用Map , 或者註解!

上圖Map負責把參數對應好,例如id對應userid,name對應username,pwd對應userpassword,傳入的時候可以不傳完全

例如下圖只傳了兩個參數,則name會為null

7. 模糊查詢

模糊查詢這麼寫?

Java程式碼執行的時候,傳遞通配符% %List<User> userList = mapper.getUserLike("%李%");

2.在sql拼接中使用通配符

select * from user where name like "%"#{value}"%"

4、配置解析

1. 核心配置檔案

mybatis-config.xmlMybatis的配置檔案包含了會深深影響MyBatis行為的設定和屬性資訊。

2. 環境配置 environments

MyBatis 可以配置成適應多種環境

不過要記住:儘管可以配置多個環境,但每個 SqlSessionFactory 例項只能選擇一種環境

學會使用配置多套運行環境!

MyBatis預設的事務管理器就是JDBC ,連線池:POOLED

3. 屬性 properties

我們可以通過properties屬性來實現引用配置檔案

這些屬性可以在外部進行配置,並可以進行動態替換。你既可以在典型的 Java 屬性檔案中配置這些屬性,也可以在 properties 元素的子元素中設定。【db.poperties】

編寫一個配置檔案

db.properties

driver=com.mysql.cj.jdbc.Driver

url=jdbc:mysql://localhost:3306/mybatis?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC

username=root

password=root

在核心配置檔案中引入

可以直接引入外部檔案可以在其中增加一些屬性配置如果兩個檔案有同一個欄位,優先使用外部配置檔案的4. 類型別名 typeAliases

類型別名可為 Java 類型設定一個縮寫名字。 它僅用於 XML 配置.意在降低冗餘的全限定類名書寫。

也可以指定一個包,每一個在包 domain.blog 中的 Java Bean,在沒有註解的情況下,會使用 Bean 的首字母小寫的非限定類名來作為它的別名。 比如 domain.blog.Author 的別名為 author,;若有註解,則別名為其註解值。見下面的例子:

<typeAliases>

<package name="com.kuang.pojo"/>

</typeAliases>

在實體類比較少的時候,使用第一種方式。

如果實體類十分多,建議用第二種掃描包的方式。

第一種可以DIY別名,第二種不行,如果非要改,需要在實體上增加註解。

@Alias("author")

public class Author {

...

}

5. 設定 Settings

這是 MyBatis 中極為重要的調整設定,它們會改變 MyBatis 的運行時行為。

6. 其他配置

typeHandlers(類型處理器)

objectFactory(物件工廠)

plugins 插件

mybatis-generator-core

mybatis-plus

通用mapper

7. 對映器 mappers

MapperRegistry:註冊繫結我們的Mapper檔案;

方式一:【推薦使用】

方式二:使用class檔案繫結註冊

注意點:

介面和他的Mapper配置檔案必須同名介面和他的Mapper配置檔案必須在同一個包下方式三:使用包掃描進行注入

8. 作用域和生命週期

聲明週期和作用域是至關重要的,因為錯誤的使用會導致非常嚴重的併發問題。

SqlSessionFactoryBuilder:

一旦創建了SqlSessionFactory,就不再需要它了局部變數SqlSessionFactory:

說白了就可以想象為:資料庫連線池SqlSessionFactory一旦被創建就應該在應用的運行期間一直存在,沒有任何理由丟棄它或重新創建一個例項。因此SqlSessionFactory的最佳作用域是應用作用域(ApplocationContext)。最簡單的就是使用單例模式或靜態單例模式。SqlSession:

連線到連線池的一個請求SqlSession 的例項不是執行緒安全的,因此是不能被共享的,所以它的最佳的作用域是請求或方法作用域。用完之後需要趕緊關閉,否則資源被佔用!5、解決屬性名和欄位名不一致的問題

1. 問題

資料庫中的欄位

新建一個項目,拷貝之前的,測試實體類欄位不一致的情況

測試出現問題

解決方法:

起別名<select id="getUserById" resultType="com.kuang.pojo.User">

select id,name,pwd as password from USER where id = #{id}

</select>

2. resultMap

結果集對映

id name pwd

id name password

resultMap 元素是 MyBatis 中最重要最強大的元素。ResultMap 的設計思想是,對簡單的語句做到零配置,對於複雜一點的語句,只需要描述語句之間的關係就行了。ResultMap 的優秀之處——你完全可以不用顯式地配置它們。如果這個世界總是這麼簡單就好了。6、日誌

6.1 日誌工廠

如果一個數據庫操作,出現了異常,我們需要排錯,日誌就是最好的助手!

曾經:sout、debug

現在:日誌工廠

SLF4JLOG4J 【掌握】LOG4J2JDK_LOGGINGCOMMONS_LOGGINGSTDOUT_LOGGING 【掌握】NO_LOGGING在MyBatis中具體使用哪一個日誌實現,在設定中設定

STDOUT_LOGGING<settings>

<setting name="logImpl" value="STDOUT_LOGGING"/>

</settings>

6.2 Log4j

什麼是Log4j?

Log4j是Apache的一個開源項目,通過使用Log4j,我們可以控制日誌資訊輸送的目的地是控制檯、檔案、GUI元件;我們也可以控制每一條日誌的輸出格式;通過定義每一條日誌資訊的級別,我們能夠更加細緻地控制日誌的生成過程;最令人感興趣的就是,這些可以通過一個配置檔案來靈活地進行配置,而不需要修改應用的程式碼。先匯入log4j的包

log4j.properties

配置settings為log4j實現

測試運行

Log4j簡單使用

在要使用Log4j的類中,匯入包 import org.apache.log4j.Logger;日誌物件,參數為當前類的class物件Logger logger = Logger.getLogger(UserDaoTest.class);

日誌級別

infodebugerror7、分頁

思考:為什麼分頁?

減少資料的處理量7.1 使用Limit分頁

SELECT * from user limit startIndex,pageSize

使用MyBatis實現分頁,核心SQL

介面//分頁

List<User> getUserByLimit(Map<String,Integer> map);

2.Mapper.xml

3.測試

7.2 RowBounds分頁

不再使用SQL實現分頁

介面//分頁2

List<User> getUserByRowBounds();

2.mapper.xml

3.測試

7.3 分頁插件

8、使用註解開發

8.1 面向介面開發

大家之前都學過面向物件程式設計,也學習過介面,但在真正的開發中,很多時候我們會選擇面向介面程式設計根本原因 :解耦,可拓展,提高複用,分層開發中,上層不用管具體的實現,大家都遵守共同的標準,使得開發變得容易,規範性更好 。

在一個面向物件的系統中,系統的各種功能是由許許多多的不同物件協作完成的。在這種情況下,各個物件內部是如何實現自己的,對系統設計人員來講就不那麼重要了;而各個物件之間的協作關係則成為系統設計的關鍵。小到不同類之間的通訊,大到各模組之間的互動,在系統設計之初都是要著重考慮的,這也是系統設計的主要工作內容。面向介面程式設計就是指按照這種思想來程式設計。

關於介面的理解:

介面從更深層次的理解,應是定義(規範,約束)與實現(名實分離的原則)的分離。介面的本身反映了系統設計人員對系統的抽象理解。介面應有兩類:. 第一類是對一個個體的抽象,它可對應為一個抽象體(抽象類 abstract class);

. 第二類是對一個個體某方面的抽象, 即形成一個抽象面(介面 interface) ;

.個體有可能有多個抽象面。抽象體與抽象面是有區別的。

三個面向區別

面向物件是指,我們考慮問題時,以物件為單位,考慮它的屬性和方法;面向過程是指,我們考慮問題時,以一個具體的流程(事務過程)為單位,考慮它的實現;介面設計與非介面設計是針對複用技術而言的,與面向物件(過程)不是一個問題,更多的體現就是對系統整體的架構;8.2 使用註解開發

註解在介面上實現

@Select("select * from user")

List<User> getUsers();

需要在核心配置檔案中繫結介面

<mappers>

<mapper class="com.kuang.dao.UserMapper"/>

</mappers>

測試

本質:反射機制實現

底層:動態代理

MyBatis詳細執行流程

8.3 註解CURD

//方法存在多個參數,所有的參數前面必須加上@Param("id")註解

@Delete("delete from user where id = ${uid}")

int deleteUser(@Param("uid") int id);

編寫介面,增加註解

測試類

注意:我們必須要將介面註冊繫結到我們的核心配置檔案中!

關於@Param( )註解

基本類型的參數或者String類型,需要加上引用類型不需要加如果只有一個基本類型的話,可以忽略,但是建議大家都加上我們在SQL中引用的就是我們這裡的@Param( )中設定的屬性名面試題:#{} 和 ${}使用的區別?

首先建議:能使用 #{} 就不要使用 ${}~~~

mybatis 中使用 Mapper.xml 裡面的配置進行 sql 查詢,經常需要動態傳遞參數,例如我們需要根據使用者的姓名來篩選使用者時,sql 如下:

select * from user where name = "AAA";

上述 sql 中,我們希望 name 後的參數 「AAA」 是動態可變的,即不同的時刻根據不同的姓名來查詢使用者。在 Mapper.xml 檔案中使用如下的 sql 可以實現動態傳遞參數 name:

動態 SQL 是 mybatis 的強大特性之一,也是它優於其他 ORM 框架的一個重要原因。mybatis 在對 sql 語句進行預編譯之前,會對 sql 進行動態解析,解析為一個 BoundSql 物件,也是在此處對動態 SQL 進行處理的。在動態 SQL 解析階段, #{ } 和 ${ } 會有不同的表現。

比如:我想讓name的值為AAA,上面那兩句程式碼解析下來的結果都是一樣的:

select * from user where name = "AAA";

但是,其解析過程中處理手段是有所不同的!

#{ }在預處理時,會把參數部分用一個佔位符 ? 代替,變成如下的 sql 語句:

select * from user where name = ?;

${ } 僅僅為一個純碎的 string 替換,在動態 SQL 解析階段將會進行變數替換。

select * from user where name = "";

綜上所得, ${ } 變數的替換階段是在動態 SQL 解析階段,而 #{ }變數的替換是在 DBMS 中。

總結:

#{ }可以防止Sql 注入,它會將所有傳入的參數作為一個字元串來處理。

$ {} 則將傳入的參數拼接到Sql上去執行,一般用於表名和欄位名參數,$ 所對應的參數應該由伺服器端提供,前端可以用參數進行選擇,避免Sql 注入的風險。

9、Lombok

Lombok項目是一個Java庫,它會自動插入編輯器和構建工具中,Lombok提供了一組有用的註釋,用來消除Java類中的大量樣板程式碼。僅五個字元(@Data)就可以替換數百行程式碼從而產生乾淨,簡潔且易於維護的Java類。

使用步驟:

在IDEA中安裝Lombok插件在項目中匯入lombok的jar包

3.在程式上加註解

說明:

示例圖:

10、多對一處理

多個學生一個老師;站在學生的角度,就是多個學生 關聯一個老師;站在老師的角度,就是一個老師 集合了很多學生。

alter table student ADD CONSTRAINT fk_tid foreign key (tid) references teacher(id)

1. 測試環境搭建

匯入lombok新建實體類Teacher,Student建立Mapper介面建立Mapper.xml檔案在核心配置檔案中繫結註冊我們的Mapper介面或者檔案 【方式很多,隨心選】測試查詢是否能夠成功2. 按照查詢巢狀處理

3.按照結果巢狀處理

回顧Mysql多對一查詢方式:

子查詢 (按照查詢巢狀)聯表查詢 (按照結果巢狀)11、一對多處理

1. 環境搭建

實體類

2. 按照結果巢狀處理

3.按照查詢巢狀處理

小結

關聯 - association 【多對一】

集合 - collection 【一對多】

javaType & ofType

JavaType用來指定實體類中的類型

ofType用來指定對映到List或者集合中的pojo類型,泛型中的約束類型

注意點:

保證SQL的可讀性,儘量保證通俗易懂注意一對多和多對一,屬性名和欄位的問題如果問題不好排查錯誤,可以使用日誌,建議使用Log4j面試高頻問題

Mysql引擎InnoDB底層原理索引索引優化12、動態SQL

什麼是動態SQL:動態SQL就是根據不同的條件生成不同的SQL語句

所謂的動態SQL,本質上還是SQL語句,只是我們可以在SQL層面,去執行一個邏輯程式碼

動態 SQL 是 MyBatis 的強大特性之一。如果你使用過 JDBC 或其它類似的框架,你應該能理解根據不同條件拼接 SQL 語句有多痛苦,例如拼接時要確保不能忘記新增必要的空格,還要注意去掉列表最後一個列名的逗號。利用動態 SQL,可以徹底擺脫這種痛苦。

if

choose (when, otherwise)

trim (where, set)

foreach

搭建環境

創建一個基礎工程

導包編寫配置檔案編寫實體類

4.編寫實體類對應Mapper介面和Mapper.xml檔案

IF

這條語句提供了可選的查詢文字功能。如果不傳入 「title」,那麼所有處於 「ACTIVE」 狀態的 BLOG 都會返回;如果傳入了 「title」 參數,那麼就會對 「title」 一列進行模糊查詢並返回對應的 BLOG 結果(細心的讀者可能會發現,「title」 的參數值需要包含查詢掩碼或通配符字元)。

測試程式碼:

choose (when, otherwise)

有時候,我們不想使用所有的條件,而只是想從多個條件中選擇一個使用。針對這種情況,MyBatis 提供了 choose 元素,它有點像 Java 中的 switch 語句。

trim(where,set)

where 元素只會在子元素返回任何內容的情況下才插入 「WHERE」 子句。而且,若子句的開頭為 「AND」 或 「OR」,where 元素也會將它們去除。

set 元素會動態地在行首插入 SET 關鍵字,並會刪掉額外的逗號(這些逗號是在使用條件語句給列賦值時引入的)

所謂的動態SQL,本質還是SQL語句,只是我們可以在SQL層面執行一個邏輯程式碼!

Foreach

foreach 元素的功能非常強大,它允許你指定一個集合,聲明可以在元素體內使用的集合項(item)和索引(index)變數。它也允許你指定開頭與結尾的字元串以及集合項迭代之間的分隔符。這個元素也不會錯誤地新增多餘的分隔符,看它多智慧!

SQL片段

有的時候,我們可能會將一些功能的部分抽取出來,方便服用!

使用SQL標籤抽取公共部分可

2.在需要使用的地方使用Include標籤引用即可

注意事項:

最好基於單標來定義SQL片段不要存在where標籤動態SQL就是在拼接SQL語句,我們只要保證SQL的正確性,按照SQL的格式,去排列組合就可以了

建議:

先在Mysql中寫出完整的SQL,再對應的去修改成我們的動態SQL實現通用即可。13、快取

13.1 簡介

查詢 : 需要連線資料庫,耗資源

一次查詢的結果,給他暫存一個可以直接取到的地方 --> 記憶體:那麼這些資料就叫做 快取

我們再次查詢的相同資料的時候,直接走快取,不走資料庫了

什麼是快取[Cache]?存在記憶體中的臨時資料。

將使用者經常查詢的資料放在快取(記憶體)中,使用者去查詢資料就不用從磁碟上(關係型資料庫檔案)查詢,從快取中查詢,從而提高查詢效率,解決了高併發系統的效能問題。

為什麼使用快取?減少和資料庫的互動次數,減少系統開銷,提高系統效率

什麼樣的資料可以使用快取?經常查詢並且不經常改變的資料 【可以使用快取】

13.2 MyBatis快取

MyBatis包含一個非常強大的查詢快取特性,它可以非常方便的定製和配置快取,快取可以極大的提高查詢效率。MyBatis系統中預設定義了兩級快取:一級快取 和 二級快取

預設情況下,只有一級快取開啟(SqlSession級別的快取,也稱為本地快取)

二級快取需要手動開啟和配置,他是基於namespace級別的快取。

為了提高可擴展性,MyBatis定義了快取介面Cache。我們可以通過實現Cache介面來定義二級快取。

13.3 一級快取

一級快取也叫本地快取:SqlSession

與資料庫同一次會話期間查詢到的資料會放在本地快取中

以後如果需要獲取相同的資料,直接從快取中拿,沒必要再去查詢資料庫

測試步驟:

開啟日誌測試在一個Session中查詢兩次記錄

3.檢視日誌輸出

說明快取一樣 ~~

快取失效的情況:

查詢不同的東西增刪改操作,可能會改變原來的資料,所以必定會重新整理快取查詢不同的Mapper.xml手動清理快取sqlSession.clearCache();

13.4 二級快取

二級快取也叫全局快取,一級快取作用域太低了,所以誕生了二級快取基於namespace級別的快取,一個名稱空間,對應一個二級快取工作機制一個會話查詢一條資料,這個資料就會被放在當前會話的一級快取中

如果會話關閉了,這個會員對應的一級快取就沒了;但是我們想要的是,會話關閉了,一級快取中的資料被儲存到二級快取中

新的會話查詢資訊,就可以從二級快取中獲取內容

不同的mapper查詢出的資料會放在自己對應的快取(map)中

一級快取開啟(SqlSession級別的快取,也稱為本地快取)

二級快取需要手動開啟和配置,他是基於namespace級別的快取。

為了提高可擴展性,MyBatis定義了快取介面Cache。我們可以通過實現Cache介面來定義二級快取。

步驟:

開啟全局快取

<!--顯示的開啟全局快取-->

<setting name="cacheEnabled" value="true"/>

在Mapper.xml中使用二級快取,可以自定義參數

測試

使用二級快取後

注意:我們需要將實體類序列化,否則就會報錯小結:

只要開啟了二級快取,在同一個Mapper下就有效所有的資料都會放在一級快取中只有當前會話提交,或者關閉的時候,才會提交到二級快取中13.5 快取原理

注意:

只有查詢才有快取,根據資料是否需要快取(修改是否頻繁選擇是否開啟)useCache=「true」

13.6 自定義快取-ehcache

Ehcache是一種廣泛使用的開源Java分散式快取。主要面向通用快取

導包

在mapper中指定使用我們的ehcache快取實現

<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>


IT145.com E-mail:sddin#qq.com