MyBatis?在?Spring?Boot?中的實(shí)踐記錄
一、什么是 MyBatis
通過(guò) MyBatis中文網(wǎng)站我們了解到 “MyBatis 是一款優(yōu)秀的持久層框架 ” ,用于簡(jiǎn)化JDBC的開(kāi)發(fā),而此處 “ 持久層 ” :指的是持久化操作的層,通常指數(shù)據(jù)訪問(wèn)層(Dao),用來(lái)操作數(shù)據(jù)庫(kù)

換句話說(shuō),MyBatis 是更簡(jiǎn)單的完成程序與數(shù)據(jù)庫(kù)交互的框架,即更簡(jiǎn)單方便地操作和讀取數(shù)據(jù)庫(kù)工具
二、 MyBatis 入門(mén)
2.1、創(chuàng)建項(xiàng)目
創(chuàng)建 Spring Boot 項(xiàng)目,并導(dǎo)入 MyBatis 啟動(dòng)依賴(lài)和 MySQL 驅(qū)動(dòng)包

創(chuàng)建用戶(hù)表,并創(chuàng)建對(duì)對(duì)應(yīng)的實(shí)體類(lèi) UserInfo

@Data
public class UserInfo {
private Integer id;
private String username;
private String password;
private Integer age;
private Integer gender;
private String phone;
private Integer deleteFlag;
private Date createTime;
private Date updateTime;
}
數(shù)據(jù)庫(kù)規(guī)范:全部小寫(xiě),單詞之間用下劃線分割( _ )
Java規(guī)范: 屬性使用小駝峰來(lái)表示
注意:我們創(chuàng)建表和實(shí)體類(lèi)中,要把數(shù)據(jù)庫(kù)字段和Java屬性一一對(duì)應(yīng)起來(lái)
2.2、配置數(shù)據(jù)庫(kù)連接字符串
在 application.yml 配置文件中配置如下:
2.3、入門(mén)操作
MyBatis 采用 “ 接口+XML/注解 ” 的方式實(shí)現(xiàn)數(shù)據(jù)訪問(wèn)層,實(shí)現(xiàn)了接口與實(shí)現(xiàn)的分離,其核心機(jī)制為:在運(yùn)行時(shí)為接口生成動(dòng)態(tài)代理對(duì)象,即自動(dòng)創(chuàng)建它的實(shí)現(xiàn)類(lèi),能夠輕松創(chuàng)建mock實(shí)現(xiàn)進(jìn)行單元測(cè)試
MyBatis 在運(yùn)行時(shí)通過(guò) ??動(dòng)態(tài)代理(Dynamic Proxy)?? 機(jī)制自動(dòng)生成了接口的實(shí)現(xiàn)類(lèi)
我們接下來(lái)查詢(xún)所有用戶(hù)
@Mapper
public interface UserInfoMapper {
@Select("SELECT * from user_info")
List<UserInfo> selectAll();
}@Mapper注解:標(biāo)識(shí)該接口為 MyBatis 的 Mapper 接口
• 運(yùn)行時(shí)框架會(huì)自動(dòng)生成接口代理對(duì)象,并交由 Spring IOC 容器管理
• @Select 注解:用于標(biāo)記查詢(xún)方法,定義對(duì)應(yīng) SQL 查詢(xún)語(yǔ)句
2.4、單元測(cè)試

測(cè)試類(lèi)已在 src/test 目錄下自動(dòng)生成,可直接用于測(cè)試
@SpringBootTest
class UserInfoMapperTest {
@Autowired
private UserInfoMapper userInfoMapper;
@Test
void selectAll() {
List<UserInfo> userInfos = userInfoMapper.selectAll();
System.out.println(userInfos);
}
}在該測(cè)試類(lèi)上添加了 @SpringBootTest 注解后,運(yùn)行時(shí)將自動(dòng)加載 Spring 運(yùn)行環(huán)境;方法加上@Test 注解后,該方法即可單獨(dú)運(yùn)行;通過(guò)@Autowired 注解注入待測(cè)試的類(lèi)后,即可開(kāi)始進(jìn)行測(cè)試
運(yùn)行結(jié)果:成功查詢(xún)了所有用戶(hù)的信息

三、MyBatis基礎(chǔ)操作(增刪改查)
3.1、配置日志
在MyBatis中我們可以借助日志,查看SQL語(yǔ)句的執(zhí)行,傳遞的參數(shù)以及執(zhí)行的結(jié)果,在application.yml 配置文件中配置(properties文件配置查閱前篇)
mybatis:
configuration: # 配置打印 MyBatis?志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl配置后可以看到

3.2、參數(shù)傳遞
查詢(xún) ID 為 3 的用戶(hù)
@Mapper
public interface UserInfoMapper {
@Select("select username,password,age,gender,phone from user_info where id = #{id}")
UserInfo selectById(Integer id);
}當(dāng) Mapper 接口方法的形參僅有一個(gè)普通類(lèi)型參數(shù)時(shí),# {...} 中的屬性名稱(chēng)可以任意指定,但是如果形參有多個(gè)普通類(lèi)型的參數(shù)時(shí),屬性名稱(chēng)必須對(duì)應(yīng)(見(jiàn)3.3例中代碼)
生成測(cè)試用例:#{id}
@Test
void selectById() {
UserInfo userInfo = userInfoMapper.selectById(3);
System.out.println(userInfo);
}查詢(xún)結(jié)果:

可通過(guò)@Param 注解設(shè)置參數(shù)別名。若使用 @Param 設(shè)置別名,#{...} 中的屬性名必須與 @Param 指定的別名保持一致
@Select("select username,password,age,gender,phone from user_info where id = #{userID}")
UserInfo selectById(@Param("userID") Integer id);
??注意:
@Select("SELECT * from user_info")
List<UserInfo> selectAll();
@Select("select username,password,age,gender,phone from user_info where id = #{userID}")
UserInfo selectById(@Param("userID") Integer id);
@Select("select username,password,age,gender,phone from user_info where age = #{age}")
List<UserInfo> selectAllByAge(Integer age);
3.3、增(Insert)
目標(biāo)SQL語(yǔ)句:

插入另一條數(shù)據(jù),并將SQL中的常量替換成動(dòng)態(tài)的參數(shù):
@Insert("insert into user_info (username, password, age, gender, phone) values (#{username}, #{password}, #{age}, #{gender}, #{phone})")
Integer insert(UserInfo userInfo); @Test
void insert() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("楚子航");
userInfo.setPassword("123456");
userInfo.setGender(1);
userInfo.setAge(19);
userInfo.setPhone("122222222222");
int result=userInfoMapper.insert(userInfo);
System.out.println("影響的行數(shù)"+result);
}在 MyBatis 中,insert() 方法返回的結(jié)果和在MySQL中返回的結(jié)果是一樣的,都是返回影響的行數(shù),觀察測(cè)試結(jié)果:

返回主鍵
我們想在插入之后,拿到剛剛插入的數(shù)據(jù)ID
@Options(useGeneratedKeys = true,keyProperty = "id")
@Insert("insert into user_info (username, password, age, gender, phone) values (#{username}, #{password}, #{age}, #{gender}, #{phone})")
Integer insert(UserInfo userInfo); @Test
void insert() {
UserInfo userInfo = new UserInfo();
userInfo.setUsername("路鳴澤");
userInfo.setPassword("123456");
userInfo.setGender(1);
userInfo.setAge(16);
userInfo.setPhone("11111111111");
int result=userInfoMapper.insert(userInfo);
System.out.println("影響的行數(shù)"+result+" id:"+userInfo.getId());
}• useGeneratedKeys:?jiǎn)⒂煤螅?strong>MyBatis 將調(diào)用 JDBC 的 getGeneratedKeys 方法來(lái)獲取數(shù)據(jù)庫(kù)自動(dòng)生成的主鍵(如 MySQL 和 SQL Server 中的自增字段),默認(rèn)值為 false
• keyProperty:指定用于標(biāo)識(shí)對(duì)象的唯一屬性,MyBatis 會(huì)通過(guò) getGeneratedKeys 的返回值或 insert 語(yǔ)句的 selectKey 子元素為其賦值

注意:
設(shè)置 useGeneratedKeys=true 后,方法返回值仍是受影響的行數(shù),自增 ID 會(huì)被自動(dòng)賦給 keyProperty 指定的屬性
3.4、刪(delete)
將上述
SQL中的常量替換為動(dòng)態(tài)參數(shù)
@Delete("delete from user_info where id = #{id}")
void deleteById(Integer id); @Test
void deleteById() {
userInfoMapper.deleteById(9);
}觀察運(yùn)行結(jié)果發(fā)現(xiàn)Id為 9 的數(shù)據(jù)已被刪除

3.5、改(update)

將上述SQL中的常量替換為動(dòng)態(tài)參數(shù)
@Update("update user_info set username = #{username} where id = #{id}")
void updateById(UserInfo userInfo); @Test
void updateById() {
UserInfo userInfo = new UserInfo();
userInfo.setId(5);
userInfo.setUsername("喜羊羊");
userInfoMapper.updateById(userInfo);
}觀察運(yùn)行結(jié)果發(fā)現(xiàn)Id為 5 的數(shù)據(jù)名稱(chēng)已經(jīng)更改為喜羊羊了

3.6、查(select)
我們?cè)俅尾樵?xún)所有信息
@Select("select id,username,password,age,gender,phone,delete_flag,create_time,update_time from user_info")
List<UserInfo> selectById(); @Test
void selectById() {
List<UserInfo> userInfoList = userInfoMapper.selectById();
System.out.println(userInfoList);
}從運(yùn)行結(jié)果可以看出,SQL語(yǔ)句中查詢(xún)了 delete_flag、create_time 和 update_time 字段,但這些字段并未被賦值

為什么呢? 這時(shí)我們會(huì)想到是不是 Java 屬性和數(shù)據(jù)庫(kù)字段對(duì)應(yīng)的名稱(chēng)不一致造成的原因呢?
@Select("select id,username,password,age,gender,phone," +
"delete_flag as deleteflag,create_time as createtime,update_time as updatetime " +
"from user_info")
List<UserInfo> selectById();
運(yùn)行結(jié)果:

MyBatis在自動(dòng)映射查詢(xún)結(jié)果時(shí),會(huì)按以下步驟處理:
- 獲取查詢(xún)結(jié)果返回的列名
- 在目標(biāo)Java類(lèi)中查找名稱(chēng)匹配的屬性(不區(qū)分大小寫(xiě))
- 當(dāng)列名與屬性名匹配時(shí)(例如數(shù)據(jù)庫(kù)列"ID"對(duì)應(yīng)Java屬性"id"),自動(dòng)將列值映射到對(duì)應(yīng)屬性
解決方法
3.6.1、起別名
如上猜測(cè),將數(shù)據(jù)庫(kù)字段名稱(chēng)通過(guò)起別名的方法與Java屬性名稱(chēng)保持一致,另外我們從下方代碼可見(jiàn)SQL語(yǔ)句可以用 + 連接
@Select("select id,username,password,age,gender,phone," +
"delete_flag as deleteflag,create_time as createtime,update_time as updatetime " +
"from user_info")
List<UserInfo> selectById();3.6.2、結(jié)果映射
@Results 注解用于建立數(shù)據(jù)庫(kù)字段與 Java 對(duì)象屬性之間的映射關(guān)系,它包含一個(gè)由 @Result 元素組成的數(shù)組,其中每個(gè)元素通過(guò) column 指定數(shù)據(jù)庫(kù)列名,property 指定對(duì)應(yīng)的 Java 屬性名,從而實(shí)現(xiàn)二者之間的映射關(guān)聯(lián)
@Results({
@Result(column = "delete_flag",property = "deleteFlag"),
@Result(column = "create_time",property = "createTime"),
@Result(column = "update_time",property = "updateTime")
})
@Select("select id,username,password,age,gender,phone,delete_flag,create_time,update_time from user_info")
List<UserInfo> selectResult();現(xiàn)在的問(wèn)題是:我們上述代碼實(shí)現(xiàn)了眾多增刪改查方法,每個(gè)方法進(jìn)行結(jié)果映射都需要字段復(fù)制操作,如果其他方法涉及不同的數(shù)據(jù)庫(kù)字段,來(lái)回修改會(huì)非常不便。在Aokey看來(lái),這并不比使用別名便利
針對(duì)這種情況,我們可以通過(guò) Id 屬性為 Results 定義別名,然后使用 @ResultMap 注解來(lái)復(fù)用其他已經(jīng)定義的 ResultMap 配置

3.6.3、 配置駝峰自動(dòng)轉(zhuǎn)換
在 application.yml 配置文件中配置如下:
mybatis:
configuration:
map-underscore-to-camel-case: true #配置駝峰?動(dòng)轉(zhuǎn)換 @Select("select id,username,password,age,gender,phone,delete_flag,create_time,update_time from user_info where age = #{age}")
List<UserInfo> selectAllByAge(Integer age);查詢(xún)結(jié)果:

到此這篇關(guān)于破繭 JDBC:MyBatis 在 Spring Boot 中的輕量實(shí)踐指南的文章就介紹到這了,更多相關(guān)mybatis springboot使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot+MybatisPlus+jdbc連接池配置多數(shù)據(jù)源的實(shí)現(xiàn)
- SpringBoot+MybatisPlus實(shí)現(xiàn)sharding-jdbc分庫(kù)分表的示例代碼
- SpringBoot+MybatisPlus+Mysql+Sharding-JDBC分庫(kù)分表
- SpringBoot多數(shù)據(jù)源配置詳細(xì)教程(JdbcTemplate、mybatis)
- SpringBoot 整合jdbc和mybatis的方法
- MyBatis框架簡(jiǎn)介及入門(mén)案例詳解
- 淺談MyBatis-plus入門(mén)使用
- MyBatis Plus 入門(mén)使用詳細(xì)教程
相關(guān)文章
使用mybatis-plus想要修改某字段為null問(wèn)題
這篇文章主要介紹了使用mybatis-plus想要修改某字段為null問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02
vscode快速引入第三方j(luò)ar包發(fā)QQ郵件
這篇文章主要介紹了vscode快速引入第三方j(luò)ar包發(fā)QQ郵件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
三道java新手入門(mén)面試題,通往自由的道路--多線程
這篇文章主要為大家分享了最有價(jià)值的3道多線程面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,對(duì)hashCode方法的設(shè)計(jì)、垃圾收集的堆和代進(jìn)行剖析,感興趣的小伙伴們可以參考一下2021-07-07
Java簡(jiǎn)單方法實(shí)現(xiàn)子任務(wù)耗時(shí)統(tǒng)計(jì)
在并發(fā)編程中,我們經(jīng)常需要將一個(gè)大任務(wù)拆分成多個(gè)子任務(wù)并行執(zhí)行,但隨之而來(lái)的問(wèn)題是如何準(zhǔn)確統(tǒng)計(jì)每個(gè)子任務(wù)的耗時(shí),下面我們來(lái)看看如何使用Java實(shí)現(xiàn)吧2026-01-01
ZooKeeper入門(mén)教程一簡(jiǎn)介與核心概念
本文是ZooKeeper入門(mén)系列教程,涵蓋ZooKeeper核心內(nèi)容,通過(guò)實(shí)例和大量圖表,結(jié)合實(shí)戰(zhàn),幫助學(xué)習(xí)者理解和運(yùn)用,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-01-01
SpringBoot?把PageHelper分頁(yè)信息返回給前端的方法步驟
本文主要介紹了SpringBoot?把PageHelper分頁(yè)信息返回給前端的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01
Java實(shí)現(xiàn)PDF轉(zhuǎn)Word的示例代碼(無(wú)水印無(wú)頁(yè)數(shù)限制)
這篇文章主要為大家詳細(xì)介紹了如何利用Java語(yǔ)言實(shí)現(xiàn)PDF轉(zhuǎn)Word文件的效果,并可以無(wú)水印、無(wú)頁(yè)數(shù)限制。文中的示例代碼講解詳細(xì),需要的可以參考一下2022-05-05
Mybatis多參數(shù)及實(shí)體對(duì)象傳遞實(shí)例講解
在使用Mybatis的時(shí)候,經(jīng)常會(huì)有各種各樣的參數(shù)傳遞,不同類(lèi)型,不同個(gè)數(shù)的參數(shù),下面小編通過(guò)例子給大家講解下Mybatis多參數(shù)及實(shí)體對(duì)象傳遞,一起看看吧2016-12-12

