SpringBoot 快速整合Mybatis(去XML化+注解進(jìn)階)

序言:使用MyBatis3提供的注解可以逐步取代XML,例如使用@Select注解直接編寫SQL完成數(shù)據(jù)查詢歹嘹,使用@SelectProvider高級(jí)注解還可以編寫動(dòng)態(tài)SQL,以應(yīng)對(duì)復(fù)雜的業(yè)務(wù)需求。

一. 基礎(chǔ)注解

MyBatis 主要提供了以下CRUD注解:

  • @Select
  • @Insert
  • @Update
  • @Delete

增刪改查占據(jù)了絕大部分的業(yè)務(wù)操作猖任,掌握這些基礎(chǔ)注解的使用還是很有必要的,例如下面這段代碼無(wú)需XML即可完成數(shù)據(jù)查詢:

@Mapper
public interface UserMapper {
    @Select("select * from t_user")
    List<User> list();
}

使用過(guò)Hibernate的同學(xué)可能會(huì)好奇瓷耙,這里為什么沒(méi)有配置映射關(guān)系也能完成屬性注入朱躺?在傳統(tǒng)項(xiàng)目中使用過(guò)Mybatis的童鞋可能很快就反應(yīng)過(guò)來(lái),是因?yàn)樵谂渲梦募虚_啟了全局駝峰映射搁痛,SpringBoot中同樣能夠做到长搀,并且更為簡(jiǎn)單快捷。

雖然開啟了全局駝峰映射鸡典,但你可能還會(huì)質(zhì)疑源请,如果不符合下劃線轉(zhuǎn)駝峰規(guī)則的字段,拿查詢回來(lái)的實(shí)體對(duì)象屬性將獲取為null彻况,比如上述User對(duì)象屬性mobileNum和對(duì)應(yīng)的數(shù)據(jù)庫(kù)字段phoneNum谁尸,則查詢結(jié)果為:

[
  {
    "userId": "1",
    "username": "admin",
    "password": "admin",
    "mobileNum": null
  },
  {
    "userId": "2",
    "username": "roots",
    "password": "roots",
    "mobileNum": null
  }
]

為了解決對(duì)象屬性和字段駝峰不一致的問(wèn)題,我們可以使用映射注解@Results來(lái)指定映射關(guān)系纽甘。

二. 映射注解

Mybatis主要提供這些映射注解:

  • @Results 用于填寫結(jié)果集的多個(gè)字段的映射關(guān)系.
  • @Result 用于填寫結(jié)果集的單個(gè)字段的映射關(guān)系.
  • @ResultMap 根據(jù)ID關(guān)聯(lián)XML里面<resultMap>.

例如上面的list方法良蛮,我們可以在查詢SQL的基礎(chǔ)上,指定返回的結(jié)果集的映射關(guān)系悍赢,其中property表示實(shí)體對(duì)象的屬性名决瞳,column表示對(duì)應(yīng)的數(shù)據(jù)庫(kù)字段名货徙。

    @Results({
            @Result(property = "userId", column = "USER_ID"),
            @Result(property = "username", column = "USERNAME"),
            @Result(property = "password", column = "PASSWORD"),
            @Result(property = "mobileNum", column = "PHONE_NUM")
    })
    @Select("select * from t_user")
    List<User> list();

查詢結(jié)果如下,:

[
  {
    "userId": "1",
    "username": "admin",
    "password": "admin",
    "mobileNum": "15011791234"
  },
  {
    "userId": "2",
    "username": "roots",
    "password": "roots",
    "mobileNum": "18812342017"
  }
]

為了方便演示和免除手工編寫映射關(guān)系的煩惱皮胡,這里提供了一個(gè)快速生成映射結(jié)果集的方法痴颊,具體內(nèi)容如下:

  /**
     * 1.用于獲取結(jié)果集的映射關(guān)系
     */
    public static String getResultsStr(Class origin) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("@Results({\n");
        for (Field field : origin.getDeclaredFields()) {
            String property = field.getName();
            //映射關(guān)系:對(duì)象屬性(駝峰)->數(shù)據(jù)庫(kù)字段(下劃線)
            String column = new PropertyNamingStrategy.SnakeCaseStrategy().translate(field.getName()).toUpperCase();
            stringBuilder.append(String.format("@Result(property = \"%s\", column = \"%s\"),\n", property, column));
        }
        stringBuilder.append("})");
        return stringBuilder.toString();
    }

在當(dāng)前Main方法執(zhí)行效果如下:然后我們將控制臺(tái)這段打印信息復(fù)制到接口方法上即可。

三. 高級(jí)注解

MyBatis-3 主要提供了以下CRUD的高級(jí)注解:

  • @SelectProvider
  • @InsertProvider
  • @UpdateProvider
  • @DeleteProvider

見(jiàn)名知意胸囱,這些高級(jí)注解主要用于動(dòng)態(tài)SQL祷舀,這里以@SelectProvider 為例,主要包含兩個(gè)注解屬性烹笔,其中type表示工具類裳扯,method 表示工具類的某個(gè)方法,用于返回具體的SQL谤职。

@Mapper
public interface UserMapper {
    @SelectProvider(type = UserSqlProvider.class, method = "list222")
    List<User> list2();
}

工具類代碼如下:

public class UserSqlProvider {
    public String list222() {
        return "select * from t_user ;
    }

四. 詳細(xì)教程

對(duì)上述注解有所了解之后饰豺,我們以具體項(xiàng)目案例來(lái)進(jìn)一步鞏固這些注解的實(shí)際使用。

具體步驟

1. 引入依賴

為了方便演示允蜈,首選搭建Web環(huán)境冤吨,另外數(shù)據(jù)庫(kù)選擇Mysql 5.5+。

    <dependencies>
        <dependency> <!--添加Web依賴 -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency> <!--添加Mybatis依賴 -->
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.1</version>
        </dependency>
        <dependency><!--添加MySQL驅(qū)動(dòng)依賴 -->
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency><!--添加Test依賴 -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

2. 添加配置

這里主要是添加數(shù)據(jù)源饶套,配置駝峰映射和開啟SQL日志的控制臺(tái)打印漩蟆。在項(xiàng)目的資源目錄中,添加 application.yml 配置如下:

spring:
  datasource:
    #連接MySQL
    url: jdbc:mysql://localhost:3306/socks?useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver

mybatis:
  configuration:
   #配置項(xiàng):開啟下劃線到駝峰的自動(dòng)轉(zhuǎn)換. 作用:將數(shù)據(jù)庫(kù)字段根據(jù)駝峰規(guī)則自動(dòng)注入到對(duì)象屬性妓蛮。
   map-underscore-to-camel-case: true

logging:
  level:
   #打印SQL信息
   com.hehe.mapper: debug

3. 編寫數(shù)據(jù)層代碼

這里以我們熟悉的用戶信息為例怠李,編寫UserMapper接口和本案例使用的UserSqlProvider。

3.1 UserMapper

添加UserMapper接口用于數(shù)據(jù)查詢:

package com.hehe.mapper;
@Mapper
public interface UserMapper {
    /**
     * 方式1:使用注解編寫SQL蛤克。
     */
    @Select("select * from t_user")
    List<User> list();

    /**
     * 方式2:使用注解指定某個(gè)工具類的方法來(lái)動(dòng)態(tài)編寫SQL.
     */
    @SelectProvider(type = UserSqlProvider.class, method = "listByUsername")
    List<User> listByUsername(String username);

    /**
     * 延伸:上述兩種方式都可以附加@Results注解來(lái)指定結(jié)果集的映射關(guān)系.
     *
     * PS:如果符合下劃線轉(zhuǎn)駝峰的匹配項(xiàng)可以直接省略不寫捺癞。
     */
    @Results({
            @Result(property = "userId", column = "USER_ID"),
            @Result(property = "username", column = "USERNAME"),
            @Result(property = "password", column = "PASSWORD"),
            @Result(property = "mobileNum", column = "PHONE_NUM")
    })
    @Select("select * from t_user")
    List<User> listSample();

    /**
     * 延伸:無(wú)論什么方式,如果涉及多個(gè)參數(shù),則必須加上@Param注解,否則無(wú)法使用EL表達(dá)式獲取參數(shù)。
     */
    @Select("select * from t_user where username like #{username} and password like #{password}")
    User get(@Param("username") String username, @Param("password") String password);

    @SelectProvider(type = UserSqlProvider.class, method = "getBadUser")
    User getBadUser(@Param("username") String username, @Param("password") String password);

}

3.2 UserSqlProvider

添加UserSqlProvider构挤,用于生成SQL的工具類 髓介。

package com.hehe.mapper;

/**
 * 主要用途:根據(jù)復(fù)雜的業(yè)務(wù)需求來(lái)動(dòng)態(tài)生成SQL.
 * <p>
 * 目標(biāo):使用Java工具類來(lái)替代傳統(tǒng)的XML文件.(例如:UserSqlProvider.java <-- UserMapper.xml)
 */
public class UserSqlProvider {
    /**
     * 方式1:在工具類的方法里,可以自己手工編寫SQL。
     */
    public String listByUsername(String username) {
        return "select * from t_user where username =#{username}";
    }

    /**
     * 方式2:也可以根據(jù)官方提供的API來(lái)編寫動(dòng)態(tài)SQL筋现。
     */
    public String getBadUser(@Param("username") String username, @Param("password") String password) {
        return new SQL() {{
            SELECT("*");
            FROM("t_user");
            if (username != null && password != null) {
                WHERE("username like #{username} and password like #{password}");
            } else {
                WHERE("1=2");
            }
        }}.toString();
    }
}

3.3 實(shí)體類User

添加實(shí)體類User

public class User {
    private String userId;
    private String username;
    private String password;
    private String mobileNum;
    //Getters & Setters
}

3.4 添加數(shù)據(jù)庫(kù)記錄

打開Navicat 查詢窗口唐础,然后只需下面這段腳本。

USE `SOCKS`;
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `USER_ID` varchar(50) ,
  `USERNAME` varchar(50) ,
  `PASSWORD` varchar(50) ,
    `PHONE_NUM` varchar(15) 
) ;

INSERT INTO `t_user` VALUES ('1', 'admin', 'admin','15011791234');
INSERT INTO `t_user` VALUES ('2', 'roots', 'roots','18812342017');

4. 編寫控制層代碼

package com.hehe.controller;

@RestController
@RequestMapping("/user/*")
public class UserController {

    @SuppressWarnings("all")
    @Autowired
    UserMapper userMapper;

    @GetMapping("list")
    public List<User> list() {
        return userMapper.list();
    }

    @GetMapping("list/{username}")
    public List<User> listByUsername(@PathVariable("username") String username) {
        return userMapper.listByUsername(username);
    }

    @GetMapping("get/{username}/{password}")
    public User get(@PathVariable("username") String username, @PathVariable("password") String password) {
        return userMapper.get(username, password);
    }

    @GetMapping("get/bad/{username}/{password}")
    public User getBadUser(@PathVariable("username") String username, @PathVariable("password") String password) {
        return userMapper.getBadUser(username, password);
    }

}

5. 啟動(dòng)和測(cè)試

啟動(dòng)工程后矾飞,訪問(wèn) http://localhost:8080/user/list 可以查看用戶列表如下:

訪問(wèn) http://localhost:8080/user/list/admin 可以查詢用戶名為admin的信息:

五. 源碼和文檔

源碼地址:SpringBoot-MyBatis-Annotation 歡迎各位Star彻犁,予以支持 。

官方文檔:Mybatis3-中文手冊(cè)

專題閱讀:《SpringBoot 布道系列》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末凰慈,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子驼鹅,更是在濱河造成了極大的恐慌微谓,老刑警劉巖森篷,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異豺型,居然都是意外死亡仲智,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門姻氨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)钓辆,“玉大人,你說(shuō)我怎么就攤上這事肴焊∏傲” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵娶眷,是天一觀的道長(zhǎng)似嗤。 經(jīng)常有香客問(wèn)我,道長(zhǎng)届宠,這世上最難降的妖魔是什么烁落? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮豌注,結(jié)果婚禮上伤塌,老公的妹妹穿的比我還像新娘。我一直安慰自己轧铁,他們只是感情好每聪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著属桦,像睡著了一般熊痴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上聂宾,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天果善,我揣著相機(jī)與錄音,去河邊找鬼系谐。 笑死巾陕,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的纪他。 我是一名探鬼主播鄙煤,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼茶袒!你這毒婦竟也來(lái)了梯刚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤薪寓,失蹤者是張志新(化名)和其女友劉穎亡资,沒(méi)想到半個(gè)月后澜共,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锥腻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年嗦董,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘦黑。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡京革,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出幸斥,到底是詐尸還是另有隱情匹摇,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布睡毒,位于F島的核電站来惧,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏演顾。R本人自食惡果不足惜供搀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望钠至。 院中可真熱鬧葛虐,春花似錦、人聲如沸棉钧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)宪卿。三九已至的诵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間佑钾,已是汗流浹背西疤。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留休溶,地道東北人代赁。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像兽掰,于是被迫代替她去往敵國(guó)和親芭碍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 1. 簡(jiǎn)介 1.1 什么是 MyBatis 孽尽? MyBatis 是支持定制化 SQL窖壕、存儲(chǔ)過(guò)程以及高級(jí)映射的優(yōu)秀的...
    笨鳥慢飛閱讀 5,519評(píng)論 0 4
  • 1 引言# 本文主要講解JDBC怎么演變到Mybatis的漸變過(guò)程,重點(diǎn)講解了為什么要將JDBC封裝成Mybait...
    七寸知架構(gòu)閱讀 76,462評(píng)論 36 980
  • Java數(shù)據(jù)持久化之mybatis 一. mybatis簡(jiǎn)介 1.1 原始的JDBC操作: Java 通過(guò) Jav...
    小Q逛逛閱讀 4,914評(píng)論 0 16
  • 每次對(duì)你來(lái)說(shuō)無(wú)理由的小情緒 你都包容我 還有呆呆 我不好,對(duì)自己沒(méi)信心艇拍,我需要改變 我要執(zhí)行狐蜕, 理想的生活一定是配...
    拾七月閱讀 211評(píng)論 0 0
  • “第四幕 年輕時(shí)的我上!請(qǐng)?jiān)谌f(wàn)人前將我斬首示眾卸夕,以愛(ài)國(guó)或叛國(guó)的名義將我傳頌,請(qǐng)將我的雙眼灌滿青銅婆瓜,在日落前凝望我愛(ài)...
    虛度_色受想行識(shí)閱讀 461評(píng)論 0 16