芋道 Spring Boot MyBatis 入門(一)之 MyBatis + XML
- 2019 年 11 月 10 日
- 筆記
摘要: 原創出處 http://www.iocoder.cn/Spring-Boot/MyBatis/ 「芋道源碼」歡迎轉載,保留摘要,謝謝!
- 1. 概述
- 2. MyBatis + XML
- 2.1 引入依賴
- 2.2 Application
- 2.3 應用配置文件
- 2.4 MyBatis 配置文件
- 2.5 UserDO
- 2.6 UserMapper
- 2.7 簡單測試
- 3. MyBatis + 註解
- 3.1 差異部分
- 3.2 UserMapper
- 3.3 簡單測試
- 4. MyBatis-Plus
- 4.1 引入依賴
- 4.2 Application
- 4.3 應用配置文件
- 4.4 UserDO
- 4.5 UserMapper
- 4.6 簡單測試
- 5. tkmybatis
- 5.1 引入依賴
- 5.2 Application
- 5.3 應用配置文件
- 5.4 MyBatis 配置文件
- 5.5 UserDO
- 5.6 UserMapper
- 5.7 簡單測試
- 666. 彩蛋
本文,我們基於 Spring Boot 2.X 版本。
1. 概述
在 DAL 數據訪問層,目前會有三種方向的解決方案:
- JDBC
- MyBatis
- JPA
艿艿自己在 知識星球 中,做過一個簡單的調研,看看大家使用哪個為主。結果是 MyBatis > JPA > JDBC 。這個也符合在知乎上看到的兩篇文章:
- 《MyBatis 為什麼在中國相當流行?》
- 《為什麼阿里巴巴的持久層採用 iBatis 框架,而不使用 hibernate 框架呢?感覺 hibernate 更厲害的樣子?》
而每個團隊使用 MyBatis 方式還有不同,主要是如下:
注意,幾種方式可以組合使用。
- MyBatis + XML
- MyBatis + 註解
- MyBatis-Plus
- tkmybatis
艿艿的團隊,最終我們使用 XML 的方式,因為 XML 便於可以看到每個表使用到的 SQL ,方便做優化和管理。 後來,考慮到提高開發效率,很多標準的資料庫的 CRUD 操作,編寫還是比較枯燥乏味浪費時間,所以使用 MyBatis-Plus 簡化。當然,一些相對複雜的 SQL ,還是會考慮使用 XML 。
下面,我們上面列的四種方式,逐個來入門。
2. MyBatis + XML
示例程式碼對應倉庫:mybatis-xml 。
本小節,我們會使用 mybatis-spring-boot-starter 自動化配置 MyBatis 主要配置。同時,在 XML 中編寫相應的 SQL 操作。
2.1 引入依賴
在 pom.xml 文件中,引入相關依賴。
<?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"> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>lab-12-mybatis</artifactId> <dependencies> <!-- 實現對資料庫連接池的自動化配置 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <!-- 本示例,我們使用 MySQL --> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency> <!-- 實現對 MyBatis 的自動化配置 --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.1</version> </dependency> <!-- 方便等會寫單元測試 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
具體每個依賴的作用,胖友自己認真看下艿艿添加的所有注釋噢。
2.2 Application
創建 Application.java 類,配置 @MapperScan 註解,掃描對應 Mapper 介面所在的包路徑。程式碼如下:
// Application.java @SpringBootApplication @MapperScan(basePackages = "cn.iocoder.springboot.lab12.mybatis.mapper") public class Application { }- `cn.iocoder.springboot.lab12.mybatis.mapper` 包路徑下,就是我們 Mapper 介面所在的包路徑。
- 建議 1 :因為這裡是做示例。實際項目中,可以考慮創建一個 MyBatisConfig 配置類,將
@MapperScan註解添加到其上。
2.3 應用配置文件
在 resources 目錄下,創建 application.yaml 配置文件。配置如下:
spring: # datasource 數據源配置內容 datasource: url: jdbc:mysql://47.112.193.81:3306/testb5f4?useSSL=false&useUnicode=true&characterEncoding=UTF-8 driver-class-name: com.mysql.jdbc.Driver username: testb5f4 password: F4df4db0ed86@11 # mybatis 配置內容 mybatis: config-location: classpath:mybatis-config.xml # 配置 MyBatis 配置文件路徑 mapper-locations: classpath:mapper/*.xml # 配置 Mapper XML 地址 type-aliases-package: cn.iocoder.springboot.lab12.mybatis.dataobject # 配置資料庫實體包路徑
具體的每個配置項,胖友自己認真看下艿艿添加的所有注釋噢。
2.4 MyBatis 配置文件
在 resources 目錄下,創建 mybatis-config.xml 配置文件。配置如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <!-- 使用駝峰命名法轉換欄位。 --> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> <typeAliases> <typeAlias alias="Integer" type="java.lang.Integer"/> <typeAlias alias="Long" type="java.lang.Long"/> <typeAlias alias="HashMap" type="java.util.HashMap"/> <typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap"/> <typeAlias alias="ArrayList" type="java.util.ArrayList"/> <typeAlias alias="LinkedList" type="java.util.LinkedList"/> </typeAliases> </configuration>
因為在資料庫中的表的欄位,我們是使用下劃線風格,而資料庫實體的欄位使用駝峰風格,所以通過 mapUnderscoreToCamelCase = true 來自動轉換。
2.5 UserDO
在 cn.iocoder.springboot.lab12.mybatis.dataobject 包路徑下,創建 UserDO.java 類,用戶 DO 。程式碼如下:
// UserDO.java public class UserDO { /** * 用戶編號 */ private Integer id; /** * 帳號 */ private String username; /** * 密碼(明文) * * ps:生產環境下,千萬不要明文噢 */ private String password; /** * 創建時間 */ private Date createTime; // ... 省略 setting/getting 方法 }對應的創建表的 SQL 如下:
CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用戶編號', `username` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '帳號', `password` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '密碼', `create_time` datetime DEFAULT NULL COMMENT '創建時間', PRIMARY KEY (`id`), UNIQUE KEY `idx_username` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
2.6 UserMapper
在 cn.iocoder.springboot.lab12.mybatis.mapper 包路徑下,創建 UserMapper 介面。程式碼如下:
// UserMapper.java @Repository public interface UserMapper { int insert(UserDO user); int updateById(UserDO user); int deleteById(@Param("id") Integer id); // 生產請使用標記刪除,除非有點想不開,嘿嘿。 UserDO selectById(@Param("id") Integer id); UserDO selectByUsername(@Param("username") String username); List<UserDO> selectByIds(@Param("ids")Collection<Integer> ids); }@Repository註解,用於標記是數據訪問 Bean 對象。在 MyBatis 的介面,實際非必須,只是為了避免在 Service 中,@Autowired注入時無需報警。@Param註解,聲明變數名。- 在方法為單參數時,非必須。
- 在方法為多參數時,必須。艿艿自己的編程習慣,禁止使用 Map 作為查詢參數,因為無法通過方法的定義,很直觀的看懂具體的用途。
- 細心的胖友,肯定會發現例如說
#selectByUsername(@Param("username") String username)等方法,是使用 By 欄位結尾,這是為什麼呢?一般情況下,在 SQL 中的WHERE條件欄位,我們建議能夠帶在方法名後。原因無它,簡單明了。如果是多個欄位,可以使用 AND 分隔。當然,如果查詢欄位比較多,可能方法名會比較長。
在 resources/mapper 路徑下,創建 UserMapper.xml 配置文件。程式碼如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.iocoder.springboot.lab12.mybatis.mapper.UserMapper"> <sql id="FIELDS"> id, username, password, create_time </sql> <insert id="insert" parameterType="UserDO" useGeneratedKeys="true" keyProperty="id"> INSERT INTO users ( username, password, create_time ) VALUES ( #{username}, #{password}, #{createTime} ) </insert> <update id="updateById" parameterType="UserDO"> UPDATE users <set> <if test="username != null"> , username = #{username} </if> <if test="password != null"> , password = #{password} </if> </set> WHERE id = #{id} </update> <delete id="deleteById" parameterType="Integer"> DELETE FROM users WHERE id = #{id} </delete> <select id="selectById" parameterType="Integer" resultType="UserDO"> SELECT <include refid="FIELDS" /> FROM users WHERE id = #{id} </select> <select id="selectByUsername" parameterType="String" resultType="UserDO"> SELECT <include refid="FIELDS" /> FROM users WHERE username = #{username} LIMIT 1 </select> <select id="selectByIds" resultType="UserDO"> SELECT <include refid="FIELDS" /> FROM users WHERE id IN <foreach item="id" collection="ids" separator="," open="(" close=")" index=""> #{id} </foreach> </select> </mapper>- 建議 1 :對於絕大多數查詢,我們是返回統一欄位,所以可以使用 標籤,定義 SQL 段。對於性能或者查詢欄位比較大的查詢,按需要的欄位查詢。
- 建議 2 :對於資料庫的關鍵字,使用大寫。例如說,
SELECT、WHERE等等。 - 建議 3 :基本是每「塊」資料庫關鍵字佔用一行,胖友可以看看艿艿寫的每一行示例。一定要排版乾淨,畢竟我們是有程式碼潔癖的男孩子。
2.7 簡單測試
創建 UserMapperTest 測試類,我們來測試一下簡單的 UserMapper 的每個操作。程式碼如下:
// UserMapperTest.java @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testInsert() { UserDO user = new UserDO().setUsername(UUID.randomUUID().toString()) .setPassword("nicai").setCreateTime(new Date()); userMapper.insert(user); } @Test public void testUpdateById() { UserDO updateUser = new UserDO().setId(1) .setPassword("wobucai"); userMapper.updateById(updateUser); } @Test public void testDeleteById() { userMapper.deleteById(2); } @Test public void testSelectById() { userMapper.selectById(1); } @Test public void testSelectByUsername() { userMapper.selectByUsername("yunai"); } @Test public void testSelectByIds() { List<UserDO> users = userMapper.selectByIds(Arrays.asList(1, 3)); System.out.println("users:" + users.size()); } }具體的,胖友可以自己跑跑,妥妥的。
如果胖友嫌棄手寫 MyBatis XML 很麻煩,可以看看 IDEA MyBatisCodeHelper-Pro 插件。在沒有使用 MyBatis-Plus 插件之前,使用過蠻長一段時間,我以前的老大也在用。 當然,也可以考慮使用 MyBatis Generator (MBG) 。

