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

一. 基礎(chǔ)注解

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

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

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

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

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

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

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

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

二. 映射注解

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

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

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

@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" 
 }
]

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

為了方便演示和免除手工編寫映射關(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ù)庫字段(下劃線)
            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ù)制到接口方法上即可妄呕。


image.png

三. 高級(jí)注解

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

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

見名知意,這些高級(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)目案例來進(jìn)一步鞏固這些注解的實(shí)際使用大莫。

1. 引入依賴

為了方便演示,首選搭建Web環(huán)境官份,另外數(shù)據(jù)庫選擇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ù)庫字段根據(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è)工具類的方法來動(dòng)態(tài)編寫SQL.
        */   
    @SelectProvider(type = UserSqlProvider.class, method = "listByUsername")   
    List<User> listByUsername(String username);   
    /**
        * 延伸:上述兩種方式都可以附加@Results注解來指定結(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();   
    /**
        * 延伸:無論什么方式,如果涉及多個(gè)參數(shù),則必須加上@Param注解,否則無法使用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的工具類 狠毯。

/**
* 主要用途:根據(jù)復(fù)雜的業(yè)務(wù)需求來動(dòng)態(tài)生成SQL.
* <p>
* 目標(biāo):使用Java工具類來替代傳統(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來編寫動(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ù)庫記錄
打開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)工程后喂很,訪問 http://localhost:8080/user/list 可以查看用戶列表如下:

image.png

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

image.png

歡迎大家加入粉絲群:963944895,群內(nèi)免費(fèi)分享Spring框架皆刺、Mybatis框架SpringBoot框架少辣、SpringMVC框架、SpringCloud微服務(wù)羡蛾、Dubbo框架漓帅、Redis緩存、RabbitMq消息痴怨、JVM調(diào)優(yōu)忙干、Tomcat容器、MySQL數(shù)據(jù)庫教學(xué)視頻及架構(gòu)學(xué)習(xí)思維導(dǎo)圖

寫在最后:

既然看到這里了浪藻,覺得筆者寫的還不錯(cuò)的就點(diǎn)個(gè)贊捐迫,加個(gè)關(guān)注唄!點(diǎn)關(guān)注爱葵,不迷路施戴,持續(xù)更新!C日伞赞哗!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市辆雾,隨后出現(xiàn)的幾起案子肪笋,更是在濱河造成了極大的恐慌,老刑警劉巖度迂,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件藤乙,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡英岭,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門湿右,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诅妹,“玉大人,你說我怎么就攤上這事毅人】越疲” “怎么了?”我有些...
    開封第一講書人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵丈莺,是天一觀的道長划煮。 經(jīng)常有香客問我,道長缔俄,這世上最難降的妖魔是什么弛秋? 我笑而不...
    開封第一講書人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任器躏,我火速辦了婚禮,結(jié)果婚禮上蟹略,老公的妹妹穿的比我還像新娘登失。我一直安慰自己,他們只是感情好挖炬,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開白布揽浙。 她就那樣靜靜地躺著,像睡著了一般意敛。 火紅的嫁衣襯著肌膚如雪馅巷。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,096評(píng)論 1 291
  • 那天草姻,我揣著相機(jī)與錄音钓猬,去河邊找鬼。 笑死碴倾,一個(gè)胖子當(dāng)著我的面吹牛逗噩,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播跌榔,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼异雁,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了僧须?” 一聲冷哼從身側(cè)響起纲刀,我...
    開封第一講書人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎担平,沒想到半個(gè)月后示绊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡暂论,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年面褐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了铸豁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片球订。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡模捂,死狀恐怖亡脸,靈堂內(nèi)的尸體忽然破棺而出颖杏,到底是詐尸還是另有隱情领突,我是刑警寧澤笋敞,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布观挎,位于F島的核電站觉痛,受9級(jí)特大地震影響役衡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜薪棒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一手蝎、第九天 我趴在偏房一處隱蔽的房頂上張望榕莺。 院中可真熱鬧,春花似錦柑船、人聲如沸帽撑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽亏拉。三九已至,卻和暖如春逆巍,著一層夾襖步出監(jiān)牢的瞬間及塘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來泰國打工锐极, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留笙僚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓灵再,卻偏偏與公主長得像肋层,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子翎迁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

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