歡迎訪問我的GitHub
https://github.com/zq2599/blog_demos
內容:所有原創文章分類彙總及配套原始碼,涉及Java、Docker、Kubernetes、DevOPS等;
MyBatis初級實戰
《MyBatis初級實戰》系列旨在通過一系列編碼實戰,和讀者一起掌握MyBatis的基本用法,幫助初學者快速運用MyBatis參與實際開發;
聚焦MyBatis
《MyBatis初級實戰》面向的是對MyBatis有興趣的讀者,向讀者們提供可用的方案和程式碼,這裡不是比較Hibernate、sqltoy-orm的地方,作者也十分認可這些ORM框架,但《MyBatis初級實戰》不參與比較;
關於MyBatis
引自官方:MyBatis 是一款優秀的持久層框架,它支援自定義 SQL、儲存過程以及高階對映。MyBatis 免除了幾乎所有的 JDBC 程式碼以及設定引數和獲取結果集的工作。MyBatis 可以通過簡單的 XML 或註解來配置和對映原始型別、介面和 Java POJO(Plain Old Java Objects,普通老式 Java 物件)為資料庫中的記錄。
實戰環境
《MyBatis初級實戰》系列的環境資訊如下:
- JDK:1.8.0_181
- mybatis-spring-boot-starter:2.1.3(對應的MyBatis:3.5.5)
- Spring Boot:2.3.2.RELEASE
- MySQL:5.7.29
- 實戰環境:win10
- 開發工具:IntelliJ IDEA 2019.2.1 (Ultimate Edition)
Spring Boot整合MyBatis常規步驟概覽
Spring Boot整合MyBatis的常規步驟如下:
- maven中新增mybatis-spring-boot-starter的依賴;
- Spring Boot的配置中指定MyBatis配置檔案的位置;
- Spring Boot的配置中指定MyBatis對映檔案的位置;
- 新增MyBatis配置檔案,後續MyBatis的常規配置集中在此;
- 對映檔案xxxMapper.xml及其對應的介面檔案;
- 業務程式碼中,Autowired註解修飾介面檔案並使用;
- 接下來開始實戰,我們們先把資料準備好;
準備資料
- 請您自行準備好MySQL服務,我這邊MySQL是部署在docker上的,可以參考《群暉DS218+部署mysql》;
- 建立名為mybatis的資料庫;
- 在mybatis資料庫下執行以下SQL,即可建立本次實戰所需資料:
USE mybatis;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(32) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
`age` int(32) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `log`;
CREATE TABLE `log` (
`id` int(32) NOT NULL AUTO_INCREMENT,
`user_id` int(32),
`action` varchar(255) NOT NULL,
`create_time` datetime not null,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO mybatis.user (id, name, age) VALUES (3, 'tom', 11);
INSERT INTO mybatis.log (id, user_id, action, create_time) VALUES (3, 3, 'read book', '2020-08-07 08:18:16');
原始碼下載
- 如果您不想編碼,可以在GitHub下載所有原始碼,地址和連結資訊如下表所示(https://github.com/zq2599/blog_demos):
名稱 | 連結 | 備註 |
---|---|---|
專案主頁 | https://github.com/zq2599/blog_demos | 該專案在GitHub上的主頁 |
git倉庫地址(https) | https://github.com/zq2599/blog_demos.git | 該專案原始碼的倉庫地址,https協議 |
git倉庫地址(ssh) | git@github.com:zq2599/blog_demos.git | 該專案原始碼的倉庫地址,ssh協議 |
- 這個git專案中有多個資料夾,本章的應用在mybatis資料夾下,如下圖紅框所示:
關於父子工程
為了整個系列的程式碼好管理,我這邊用maven建立的是父子工程,如果您只要子工程,不需要父子結構,要對子工程的pom.xml做以下調整:
- parent節點原本如下:
<parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
請替換成以下內容(也就是直接用>spring-boot-starter-parent作為父工程):
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
- 子工程種的dependency節點中沒有version子節點,這些都放在父工程的dependencyManagement中統一管理了,請您將version新增到子工程的各個dependency節點:
- 接下來開始編碼
建立父工程
建立名為mybatis的maven工程,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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<modules>
<module>simple</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
- 至此,準備工作算是全部完成了,接下來我們們開始建立一個典型的Spring Boot整合MyBatis的專案吧;
Spring Boot整合MyBatis
- 在父工程mybatis之下新建名為simple的Spring Boot子工程,其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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>simple</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>simple</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- Spring Boot配置檔案是simple/src/main/resources/application.yml,內容如下:
server:
port: 8080
spring:
# 資料來源
datasource:
username: root
password: 123456
url: jdbc:mysql://192.168.50.43:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
# mybatis配置
mybatis:
# 配置檔案所在位置
config-location: classpath:mybatis-config.xml
# 對映檔案所在位置
mapper-locations: classpath:mappers/*Mapper.xml
# 日誌配置
logging:
level:
root: INFO
com:
bolingcavalry:
simple:
mapper: debug
- 新建user表對應的實體類User.java:
package com.bolingcavalry.simple.entity;
/**
* @Description: 實體類
* @author: willzhao E-mail: zq2599@gmail.com
* @date: 2020/8/4 8:24
*/
public class User {
private Integer id;
private String name;
private Integer age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
- 新建log表對應的實體類Log.java:
package com.bolingcavalry.simple.entity;
import java.sql.Date;
/**
* @Description: 實體類
* @author: willzhao E-mail: zq2599@gmail.com
* @date: 2020/8/4 8:24
*/
public class Log {
private Integer id;
private Integer userId;
private String action;
private Date createTime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "Log{" +
"id=" + id +
", userId=" + userId +
", action='" + action + '\'' +
", createTime=" + createTime +
'}';
}
}
- 接下來會新建三個配置檔案,先來看下它們的位置,以免後面放錯地方引起不必要的麻煩:
6. application.yml所在目錄下,新增名為mybatis-config.xml的檔案,這是mybatis的配置檔案,本例很簡單隻有一個配置,內容如下:
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<!-- 對映檔案中的類不用寫全路徑了-->
<package name="com.bolingcavalry.simple.entity"/>
</typeAliases>
</configuration>
- resources/mappers目錄下,新增名為UserMapper.xml的檔案,和user表相關的查詢都在此,本文只有一個查詢user表的操作,注意下文中的resultType等於User,這裡沒有寫User類的完整路徑,是因為前面mybatis-config.xml檔案中配置了typeAliases的package節點的緣故:
<?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="com.bolingcavalry.simple.mapper.UserMapper">
<select id="sel" parameterType="int" resultType="User">
select * from user where id = #{id}
</select>
</mapper>
- 再新增LogMapper.xml,如下所示,log表中的user_id欄位在Log.java中沒有同名的欄位,因此要新增resultMap來建立資料庫和實體類的欄位對映關係,再在select節點用上這個關係,注意要用resultMap屬性(UserMapper.xml中用的是resultType):
<?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="com.bolingcavalry.simple.mapper.LogMapper">
<resultMap id="logResultMap" type="Log">
<id property="id" column="id" />
<result column="user_id" jdbcType="INTEGER" property="userId" />
<result column="action" jdbcType="VARCHAR" property="action" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
</resultMap>
<select id="sel" parameterType="int" resultMap="logResultMap">
select * from log where id = #{id}
</select>
</mapper>
- 接下來是業務要用到的介面檔案,第一個是UserMapper.java:
package com.bolingcavalry.simple.mapper;
import com.bolingcavalry.simple.entity.User;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper {
User sel(int id);
}
- 第二個是LogMapper.java:
package com.bolingcavalry.simple.mapper;
import com.bolingcavalry.simple.entity.Log;
import org.springframework.stereotype.Repository;
@Repository
public interface LogMapper {
Log sel(int id);
}
- 上述兩個類都使用了Repository註解,作用是避免在編碼過程中,IDEA給出紅線提示,如下圖:
12. 對映配置完畢,接下來就可以在應用中使用了,先為user做一個service類UserService.java,裡面通過Autowired註解注入UserMapper的實現:
package com.bolingcavalry.simple.service;
import com.bolingcavalry.simple.entity.User;
import com.bolingcavalry.simple.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
UserMapper userMapper;
public User sel(int id){
return userMapper.sel(id);
}
}
- 再為log做service類LogService.java:
package com.bolingcavalry.simple.service;
import com.bolingcavalry.simple.entity.Log;
import com.bolingcavalry.simple.mapper.LogMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class LogService {
@Autowired
LogMapper logMapper;
public Log sel(int id){
return logMapper.sel(id);
}
}
- 最後是響應web請求的controller類,第一個是UserController.java:
package com.bolingcavalry.simple.controller;
import com.bolingcavalry.simple.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("user/{id}")
public String GetUser(@PathVariable int id){
return userService.sel(id).toString();
}
}
- 然後是LogController.java:
package com.bolingcavalry.simple.controller;
import com.bolingcavalry.simple.service.LogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class LogController {
@Autowired
private LogService logService;
@RequestMapping("log/{id}")
public String log(@PathVariable int id){
return logService.sel(id).toString();
}
}
- 最後是引導類SimpleApplication.java,注意MapperScan註解會自動掃描包路徑下的所有介面,這樣UserMapper和LogMapper就不用加Mapper註解了:
package com.bolingcavalry.simple;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.bolingcavalry.simple.mapper")
public class SimpleApplication {
public static void main(String[] args) {
SpringApplication.run(SimpleApplication.class, args);
}
}
- 至此,編碼完成,可以啟動驗證了;
驗證
- 啟動SpringBoot應用的方式有兩種,最簡單的辦法是再IDEA中直接啟動,如下圖:
- 第二種是simple的目錄下執行mvn clean package -U,就會在target目錄得到檔案simple-0.0.1-SNAPSHOT.jar,再執行java -jar simple-0.0.1-SNAPSHOT.jar即可啟動;
- 在瀏覽器訪問http://localhost:8080/user/3,可以得到user表的查詢結果:
4. 訪問http://localhost:8080/log/3,可以得到log表的查詢結果:
5. 在控制檯可以看到日誌如下所示,這是我們開發期間除錯問題的重要線索:
至此,入門級SpringBoot整合MyBatis的實戰就完成了,接下來的系列內容會有更多實戰,我們們一起來學習和掌握MyBatis的基本用法;
你不孤單,欣宸原創一路相伴
歡迎關注公眾號:程式設計師欣宸
微信搜尋「程式設計師欣宸」,我是欣宸,期待與您一同暢遊Java世界...