前言
SpringData是Spring提供的一個用於簡化資料庫訪問、支援雲服務的開源框架。它是一個傘形專案,包含了大量關係型資料庫及非關係型資料庫的資料訪問解決方案,其設計目的是為了使我們可以快速且簡單地使用各種資料訪問技術。
SpringBoot預設採用整合SpringData的方式統一處理資料訪問層,通過新增大量自動配置,引入各種資料訪問模板xxxTemplate以及統一的Repository介面,從而達到簡化資料訪問層的操作。
SpringData提供了多種型別資料庫支援,對支援的資料庫進行了整合,提供了各種依賴啟動器,常見資料庫依賴啟動器如下表所示:
除此之外,還有一些框架技術,SpringData專案並沒有進行統一管理,SpringBoot官方也沒有提供對應的依賴啟動器,但是為了迎合市場開發需求,這些框架技術的開發團隊自己適配了對應的依賴啟動器,例如,mybatis-spring-boot-starter支援MyBatis的使用。
SpringBoot整合MyBatis
MyBatis是一款優秀的持久層框架,雖然SpringBoot官方並沒有對Mybatis進行整合,但是Mybatis技術團隊自行適配了對應的啟動器,進一步簡化了使用Mybatis進行資料的操作。
SpringBoot整合MyBatis的步驟非常簡單,只需要引入相關的依賴啟動器,再進行資料庫相關設定即可。
基礎環境搭建
1、資料準備
在MySQL中,執行以下sql指令碼:
# 建立資料庫
CREATE DATABASE springbootdata;
# 選擇使用資料庫
USE springbootdata;
# 建立表t_article並插入相關資料
DROP TABLE IF EXISTS t_article;
CREATE TABLE t_article (
id INT(20) NOT NULL AUTO_INCREMENT COMMENT '文章id',
title VARCHAR(200) DEFAULT NULL COMMENT '文章標題',
content LONGTEXT COMMENT '文章內容',
PRIMARY KEY (id)
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO t_article VALUES ('1', 'SpringBoot基礎入門', '從入門到放棄...');
INSERT INTO t_article VALUES ('2', 'SpringCloud基礎入門', '從入門到轉行...'); # 建立表t_comment並插入相關資料
DROP TABLE IF EXISTS t_comment;
CREATE TABLE t_comment (
id INT(20) NOT NULL AUTO_INCREMENT COMMENT '評論id',
content LONGTEXT COMMENT '評論內容',
author VARCHAR(200) DEFAULT NULL COMMENT '評論作者',
a_id INT(20) DEFAULT NULL COMMENT '關聯的文章id',
PRIMARY KEY (id)
) ENGINE=INNODB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
INSERT INTO t_comment VALUES ('1', '很好、很詳細', 'luccy', '1');
INSERT INTO t_comment VALUES ('2', '贊一個', 'tom', '1');
INSERT INTO t_comment VALUES ('3', '很全面', 'eric', '1');
INSERT INTO t_comment VALUES ('4', '很好、很全面', '張三', '1');
INSERT INTO t_comment VALUES ('5', '很不錯', '李四' ,'2');
以上指令碼建立了一個名為springbootdata的資料庫,然後建立了兩張資料表:t_article和t_comment並向這兩張表插入相關資料,其中評論表t_comment的a_id與文章表t_article的主鍵id相關聯。
2、建立專案,引入相應的啟動器
引入這兩個依賴器建立專案,在專案pom.xml檔案會出現以下依賴:
3、編寫與資料庫t_article和t_comment和對應的實體類Comment和Article
package com.hardy.springbootdata.entity; /**
* @Author: HardyYao
* @Date: 2021/6/12
*/
public class Article { private Integer id; private String title; private String content; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getTitle() {
return title;
} public void setTitle(String title) {
this.title = title;
} public String getContent() {
return content;
} public void setContent(String content) {
this.content = content;
} @Override
public String toString() {
return "Article{" +
"id=" + id +
", title='" + title + '\'' +
", content='" + content + '\'' +
'}';
}
}
package com.hardy.springbootdata.entity; /**
* @Author: HardyYao
* @Date: 2021/6/12
*/
public class Comment { private Integer id; private String content; private String author; private Integer aId; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getContent() {
return content;
} public void setContent(String content) {
this.content = content;
} public String getAuthor() {
return author;
} public void setAuthor(String author) {
this.author = author;
} public Integer getaId() {
return aId;
} public void setaId(Integer aId) {
this.aId = aId;
} @Override
public String toString() {
return "Comment{" +
"id=" + id +
", content='" + content + '\'' +
", author='" + author + '\'' +
", aId=" + aId +
'}';
}
}
4、編寫配置檔案
# MySQL資料庫連線配置
spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
使用註解的方式整合Mybatis
(1)編寫針對t_comment資料表的mapper資料操作介面
package com.hardy.springbootdata.mapper; import com.hardy.springbootdata.entity.Comment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select; /**
* @Author: HardyYao
* @Date: 2021/6/12
*/
@Mapper
public interface CommentMapper { @Select("SELECT * FROM t_comment WHERE id =#{id}")
Comment findById(Integer id); }
針對該介面類的講解:@Mapper註解表示該類是一個MyBatis介面檔案,並保證能夠被SpringBoot自動掃描到Spring容器中。
這裡有個問題,如果編寫的Mapper介面過多時,那麼就需要在很多個介面類上面新增@Mapper註解,這樣會比較耗時間。為了解決這個問題,可以直接在SpringBoot專案啟動類上新增@MapperScan("xxx")註解(如 @MapperScan("com.hardy.springbootdata.mapper")),這樣就不需要再逐個新增@Mapper註解。(@MapperScan註解作用和@Mapper註解相似,但它必須指定需要掃描的具體包名)。
(2)編寫測試方法
package com.hardy.springbootdata; import com.hardy.springbootdata.entity.Comment;
import com.hardy.springbootdata.mapper.CommentMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest
class SpringbootdataApplicationTests { @Autowired
private CommentMapper commentMapper; @Test
void contextLoads() {
Comment comment = commentMapper.findById(1);
System.out.println(comment);
} }
控制檯列印結果:
由上圖可知,查詢到的Comment的aId值為null,沒有對映成功。這是因為編寫的實體類Comment中使用了駝峰命名方式將t_comment表中的a_id欄位設計成了aId屬性,所以無法正確對映查詢結果。
為了解決這個問題,可以在SpringBoot全域性配置檔案application.properties中新增開啟駝峰命名匹配對映配置,示例程式碼如下:
# 開啟駝峰命名匹配對映
mybatis.configuration.map-underscore-to-camel-case=true
再次執行測試方法,控制檯列印結果:
可以看到,這次aId對映成功了。
使用配置檔案的方式整合MyBatis
(1)編寫針對t_article資料表的mapper資料操作介面
package com.hardy.springbootdata.mapper; import com.hardy.springbootdata.entity.Article;
import org.apache.ibatis.annotations.Mapper; /**
* @Author: HardyYao
* @Date: 2021/6/12
*/
@Mapper
public interface ArticleMapper { Article selectArticle(Integer id); }
(2)建立XML對映檔案
在resources目錄下建立一個統一管理對映檔案的mapper包,並在該包下編寫與ArticleMapper介面相應的對映檔案ArticleMapper.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="com.hardy.springbootdata.mapper.ArticleMapper"> <select id="selectArticle" resultType="com.hardy.springbootdata.entity.Article">
select * from t_article where id = #{id, jdbcType=BIGINT}
</select> </mapper>
(3)配置XML對映檔案路徑。前面我們編寫的XML檔案,SpringBoot是無法自己感知到的,即SpringBoot無法掃描到我們編寫的XML配置檔案,所以我們還需要在全域性配置檔案application.properties中新增MyBatis對映檔案路徑的配置,同時需要新增實體類別名對映路徑,示例程式碼如下:
# 配置Mybatis的XML配置檔案路徑
mybatis.mapper-locations=classpath:mapper/*.xml
# 配置XML對映檔案中指定的實體類別名路徑
mybatis.type-aliases-package=com.hardy.springbootdata.entity
(4)編寫單元測試進行介面方法測試
@Autowired
private ArticleMapper articleMapper; @Test
public void selectArticle() {
Article article = articleMapper.selectArticle(1);
System.out.println(article);
}
列印結果: