SpringBoot整合Mybatis超詳細流程


前言

MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名為MyBatis 。2013年11月遷移到Github。

MyBatis 是一款優秀的持久層框架,它支持自定義 SQL、存儲過程以及高級映射。MyBatis 免除了幾乎所有的 JDBC 代碼以及設置參數和獲取結果集的工作。

MyBatis 可以通過簡單的 XML 或注解來配置和映射原始類型、接口和 Java POJO(Plain Ordinary Java Object,普通老式 Java 對象)為數據庫中的記錄。

 

 

 

因為 Mybatis的性能非常不錯,SpringBoot 官方推薦使用 Mybatis 來連接數據庫進行 CRUD 操作。

Mybatis的官方文檔地址:https://mybatis.org/mybatis-3/zh/index.html

 

詳細流程

我們使用 IDEA 建立一個 SpringBoot 項目

初始化組件部分選擇 Web、JDBC API、MyBatis Framework、MySQL Driver

 

 

 項目初始化完成之后,可以在 pom.xml 文件中看到如下依賴

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</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>

2.創建程序目錄

我們在 com.example 目錄下新建四個目錄,分別是 controller、dao、entity、service。

controller層負責具體的業務模塊流程的控制
entity層用於存放我們的實體類,與數據庫中的屬性值基本保持一致,實現set和get的方法
dao層主要是做數據持久層的工作,負責與數據庫聯絡,封裝了增刪改查基本操作
service層主要負責業務模塊的邏輯應用設計,具體要調用到已定義的DAO層的接口

然后在 resource 目錄下新建 mapper 目錄。這個 mapper 目錄是用來存放 SQL 語句的地方。

 

順便提一下,我們知道的 MVC 框架,即 model-view-controller 三層架構。這里 model層=entity層,與數據庫的數據表對應,view層和 controller層結合非常緊密,需要聯合起來一起開發。可以簡單理解為 view層是做前端界面的展示,controller層做業務模流程塊的控制。

如果在網上看到有 mapper層這個概念,就記住,mapper層=dao層,就是對數據庫進行數據持久化操作。

不管是什么框架,我們很多時候都會與數據庫進行交互。如果遇到一個場景我們都要去寫SQL語句,那么我們的代碼就會很冗余。所以,我們就想到了把數據庫封裝一下,讓我們的數據庫的交道看起來像和一個對象打交道,這個對象通常就是DAO。當我們操作這個對象的時候,這個對象會自動產生SQL語句來和數據庫進行交互,我們就只需要使用DAO就行了。

通常我們在DAO層里面寫接口,里面有與數據打交道的方法。SQL語句通常寫在mapper文件里面的。

Service層是建立在DAO層之上的,建立了DAO層后才可以建立Service層,而Service層又是在Controller層之下的,因而Service層應該既調用DAO層的接口,又要提供接口給Controller層的類來進行調用,它剛好處於一個中間層的位置。每個模型都有一個Service接口,每個接口分別封裝各自的業務處理方法。

3.理解后台訪問流程

 

 

用戶從頁面前端,也就是我們所說的 view 層進行查詢訪問,進入到 controller 層找到對應的接口,接 着 controller 進行對 service 層進行業務功能的調用,service 要進入 dao 層查詢數據,dao 層調用 mapper.xml 文件生成 sql 語句到數據庫中進行查詢。

在數據庫中查詢到數據,dao 層拿到實體對象的數據,接着交付給 service 層,接着 service 進行業務 邏輯的處理,返回結果給 controller,controller 根據結果進行最后一步的處理,返回結果給前端頁 面。

創建一個訪問用戶信息的流程為:entity->dao->mapper->service->controller,這里 mapper 指的是存放 SQL 語句的 xml 文件。

4.核心文件配置

這里我們可以使用 application.properties 文件,也可以使用 application.yml 文件來進行配置,當然推薦使用 application.yml 文件。

如果用 application.yml 在第一次啟動項目的時候報錯,項目右側 maven -> lifecycle -> clean一下即可。


server:
port: 8080
servlet:
context-path: /

spring:
datasource:
url: jdbc:mysql://localhost:3306/reserver?useUnicode=true & characterEncoding=utf-8 &
useSSL=true & serverTimezone=Asia/Shanghai
username: root
password: 666888
driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
mapper-locations: classpath:/static/mapper/*.xml
type-aliases-package: com.example.springboot.pojo

這里注意 com.mysql.jdbc.Driver 和 com.mysql.cj.jdbc.Driver。前者是 mysql-connector-java 5 中的,后者是 mysql-connector-java 6 中的(需要設置時區),相當於說一個是舊版,一個是新版。我們可以到 pom.xml 文件中查看 mysql 驅動版本,而現在基本都是 6 以上的新版本,所以直接使用后者即可。

特別強調一點,連接MySQL時使用的是spring.datasource.username,不要順手打成spring.datasource.data-username,這個教訓太深刻了。
參數解讀:

driver-class-name:mysql驅動
url:mysql連接的url,默認是3306端口,zzz是數據庫名,useSSL是使用安全套階層連接進行數據傳輸(如果true出錯可以選擇false),serverTimezone設置時區,亞洲時區請設置上海或者香港,不要設置北京,因為系統里沒有這個時區。
username 是用戶名,password 是密碼
mybatis.mapper-locations:用於將配置路徑下的 * .xml 文件加載到 mybatis 中

# 方法一:只有一個路徑
mybatis.mapper-locations= classpath:mapper/*.xml

# 方法二:有多個路徑
mybatis.mapper-locations= classpath:mapper/*.xml,classpath:mapper/user/*.xml

  • type-aliases-package:指定POJO掃描包來讓 mapper.xml 文件的 resultType 自動掃描到自定義POJO,這樣就不用每次指定完全限定名

# mapper.xml文件中設置

# 完全限定名
<select id="getUsers" resultType="com.example.entity.User">

# 指定了POJO掃描包之后
<select id="getUsers" resultType="User">

5.編寫entity

我們在編寫entity時遵循POJO的思想。

這里需要提及“POJO最小侵入性編程”的概念,POJO(Plain Ordinary Java Object)意思是普通Java對象。類的成員是私有的,且有一系列的 setter and getter方法來提供訪問。

POJO的內在含義是指那些沒有從任何類繼承、也沒有實現任何接口,更沒有被其它框架侵入的java對象。POJO的格式是用於數據的臨時傳遞,它只能裝載數據,作為數據存儲的載體,而不具有業務邏輯處理的能力。

一般來講,是 entity 中要取的數據應該和數據表相對應,但不一定要全部取出。

我們在剛才建立的 entity 目錄中新建 User 類,定義屬性 id、username、age。

public class Student {
private String sId;

private String sName;

private String sBirth;

private String sSex;

public String getsId() {
return sId;
}

public void setsId(String sId) {
this.sId = sId ;
}

public String getsName() {
return sName;
}

public void setsName(String sName) {
this.sName = sName == null ? null : sName.trim();
}

public String getsBirth() {
return sBirth;
}

public void setsBirth(String sBirth) {
this.sBirth = sBirth == null ? null : sBirth.trim();
}

public String getsSex() {
return sSex;
}

public void setsSex(String sSex) {
this.sSex = sSex == null ? null : sSex.trim();
}
}

6.編寫dao

springboot 集成 mybatis 開發有兩種版本,注解版和配置文件版。

注解版不需要配置任何文件,拿來即用,主要依靠的是注解來生成 sql 語句。配置文件版與注解版相比,僅僅稍微復雜一點,兩者的區別僅為mapper層處理的處理方式不一樣。配置文件版多了一個xml文件,但是配置更加靈活,邏輯結構更加清晰,可讀性更強。
注解版,用 @Mapper 注解標識,我們使用#{id}來標識參數。@Mapper 注解把 mapper 這個 DAO 交給 Spring 管理,不再寫 mapper 映射文件

@Mapper
public interface UserDao {
@Select("select * from user where id=#{id}")
public User getUserById(int id);

@Delete("delete from user where id=#{id}")
public int deleteUserById(int id);
}

配置文件版,需要給編寫的 dao 增加注解 @Repository。

@Repository注解修飾哪個類,則表明這個類具有對對象進行CRUD(增刪改查)的功能。

而且@Repository是@Component注解的一個派生品,所以被@Repository注解的類可以自動的被@ComponentScan 通過路徑掃描給找到。因此@Repository注解的類也能@Autowired實現自動裝配。
通常將dao接口注入到service層的時候,需要寫@Resource這個注解。加上@Repository,就是springboot生成一個bean,自動注入service的相關引用中。

我們在 dao 目錄中新建 UserDao 接口,定義好方法。

/*
實現兩個功能
1、根據用戶id查詢用戶信息
2、查詢同一年齡下的所有用戶

返回一組數據我們用 List<E> 來存儲,傳遞多個參數我們用 Map 來存儲
例如 public List<User> selectById4(@Param("map") Map map);
*/
@Repository
public interface UserDao {
//不使用@Param
public User getUserById(Integer id);
//使用@Param
public User getUserById(@Param("id") int id);

public List<User> getUserByAge(@Param("age") int age);

}

我們推薦使用 @Param 進行傳參,當映射器方法需要多個參數時,這個注解可以被用於:給映射器方法中的每個參數來取一個名字。這里有兩點好處:

在 xml 文件中不需要再指定參數類型 parameterType
當傳遞對象時,使用 #{對象.屬性} 可以更清晰地提示自己
如果不使用 @Param,多參數將會以它們的順序位置和SQL語句中的表達式進行映射,這是默認的。

dao 層定義了接口,不需要寫具體的實現類,我們只需要在 mapper 中將文件路徑映射好就行了。DAO的實現原理:它是通過JDK動態代理方式實現的,我們在啟動加載配置文件的時候,它會根據 mapper 的 xml文件去生成一個DAO的實現。

使用配置文件版時,我們還需要在主程序中通過使用@MapperScan可以指定要掃描的Mapper類的包的路徑。
@MapperScan是要spring啟動時,掃描到所有的Mapper文件,並生成代理類交給spring容器管理;

對着 dao 目錄點擊鼠標右鍵,選擇 copy reference 即可復制包路徑,粘貼進 MapperScan 中即可。

@MapperScan("com.example.dao")
@SpringBootApplication
public class SpringmybatisApplication {
public static void main(String[] args) {
SpringApplication.run(SpringmybatisApplication.class, args);
}
}

7.編寫Mapper

在 mapper 目錄下新建 UserMapper.xml 文件。

mapper.xml 的文件頭信息我們一般不會去記憶,都是直接從官網給出的教程中復制 xml 的頭信息,網址是:https://mybatis.org/mybatis-3/zh/getting-started.html

我們需要更改命名空間 namespace 使之對應我們編寫的 DAO,SQL語句都寫在 mapper 標簽里面。

<?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.example.dao.UserDao">

</mapper>

然后我們根據 UserDao 中要寫的方法進行配置,為了方便展示,我們這里僅做查詢,現在 UserDao 中有兩個查詢方法。

查詢的話我們用 select 標簽,id 指定為方法名,resultType指明返回類型,標簽中間寫 SQL 語句。因為我們已經配置了type-aliases-package,直接寫 User 即可。

<select id="getUserById" resultType="User">
select * from `user` where id=#{id}
</select>
<select id="getUserById2" resultType="User">
select * from `user` where age=#{age}
</select>

我們在前面第四步核心文件配置的時候指定了 POJO 掃描包,所以這里 resultType 不需要完全限定名。

這里 user 表完全可以不寫反引號,寫反引號主要是為了方便我們區分,這是數據庫的一個表。

編寫 Mapper.xml 文件主要注意三點:

namespace相對應
id相對應
resultType相對應
目前我們所講的 resultType 返回單一類型的值,包括基礎類型 String、Integer、Long,還有定義好的 Class 對象。

resultMap 則可以返回多個類型的值,適合多表連接查詢。resultMap 的具體用法可以去官方文檔中學習,這里我們不做過多的了解。

8.編寫Service

我們需要在實現類中使用 @Service 注解,才能被 SpringBoot 掃描,在 Controller 中使用 @Autowired 注入

在 service 目錄中新建 UserService 類

//這里只使用 @Service 也可以,括號里的內容不影響
@Service("UserService")
public class UserService {

}

使用 @Autowired 注解自動裝配 UserDao。調用 dao 層接口設計邏輯應用

@Service("UserService")
public class UserService {

@Autowired
private UserDao userDao;

public User queryUser(int id){
return userDao.getUserById(id);
}
public List<User> queryUser2(int age){
return userDao.getUserByAge(age);
}
}

/*傳遞多個參數我們可以用 Map 來實現
public List<User> queryUser4(Integer age, Integer start, Integer move){
Map<String,Object> hashMap=new HashMap<>();
hashMap.put("age",age);
hashMap.put("start",start);
hashMap.put("move",move);
return userDao.selectById4(hashMap);
}
*/

9.編寫Controller

在 controller 目錄中新建 UserController 類

這里我們使用 Restful 風格,直接返回數據。

使用 @Autowired 注解自動裝配 UserService。編寫接口為 UserService 傳輸數據

@RestController
public class UserController {

@Autowired
private UserService userService;

@GetMapping("/getUser")
public User getUser(@RequestParam("id") int id){
return userService.queryUser(id);
}
@GetMapping("/getUser2")
public List<User> getUser2(@RequestParam("age") int age){
return userService.queryUser2(age);
}
}

10.運行項目

運行 SpringBoot 項目,我們在瀏覽器的地址欄中輸入:

localhost:8081/getUser?id=1
localhost:8081/getUser2?age=20

即可看到返回了 id=1 和 age=20 的用戶的 JSON 數據。因為這里是直接在地址欄輸入參數和值,是采用 get 方式傳輸的,所以必須使用 GetMapping。

 

 

到這一步,整個的后台訪問流程就全部打通了,大家仔細理解其中的邏輯,多多揣摩。

參考文章
Mybatis官方文檔

Springboot與MyBatis簡單整合

spring boot框架mybatis.mapper-locations配置問題詳解

MySQL驅動和時區設置

SpringBoot整合Mybatis完整詳細版

mybatis返回值類型及正確使用resultType和resultMap

Mybatis實現數據持久化的三種方式


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM