天天看點

Java實戰幹貨|Spring Boot整合MyBatis架構快速實作資料操作

作者:java易

一. Spring Boot資料通路概述

Spring Data是Spring提供的一個用于簡化資料庫通路、支援雲服務的開源架構。它是一個傘形項目,包含了大量關系型資料庫及非關系型資料庫的資料通路解決方案,其設計目的是使我們可以快速且簡單地使用各種資料通路技術。Spring Boot預設采用整合Spring Data的方式統一處理資料通路層,通過添加大量自動配置,引入各種資料通路模闆xxxTemplate以及統一的Repository接口,進而達到簡化資料通路層的操作。

Spring Data提供了多種類型資料庫支援,Spring Boot對Spring Data支援的資料庫進行了整合管理,提供了各種依賴啟動器。通過一張表羅列Spring Boot提供的常見資料庫依賴啟動器。

名稱 描述
mybatis-spring-boot-starter MyBatis啟動器
mybatis-plus-boot-starter MyBatis-Plus啟動器
spring-boot-starter-data-jpa Spring Data JPA與Hibernate的啟動器
spring- boot starter-data-redis Redis鍵值資料存儲與Spring Data Redis和Jedis用戶端的啟動器
spring-boot-starter-data-neo4j Neo4j圖資料庫和Spring Data Neo4j的啟動器
spring-boot-starter-data-mongodb MongoDB和Spring Data MongoDB的啟動器

二. Spring Boot整合MyBatis實作

MyBatis是一款優秀的持久層架構,它支援定制化SQL、存儲過程以及進階映射,避免了幾乎所有的JDBC代碼和手動設定參數以及擷取結果集。MyBatis可以使用簡單的XML或注解配置和映射原生資訊,并将接口和Java的POJO(Plain Old Java Objects,普通Java對象)映射成資料庫中的記錄。

MyBatis作為操作資料庫的流行架構,Spring Boot沒有提供MyBatis場景依賴,但是MyBatis開發團隊自己适配了Spring Boot,提供了mybatis-spring-starter依賴啟動器實作資料通路操作。進一步簡化了MyBatis對資料的操作。

1.基礎環境搭建

實作Spring Boot與資料通路層架構(例如MyBatis)的整合非常簡單,主要是引入對應的依賴啟動器,并進行資料庫相關參數設定即可。

1.1 資料準備

在MySQL中建立一個名稱為springbootdata的資料庫。

# 建立資料庫
CREATE DATABASE springbootdata character SET utf8;           

在該資料庫中建立兩個表t_article和t_comment。

# 選擇使用資料庫
USE springbootdata;

# 建立文章表t_article并插入相關資料
DROP TABLE IF EXISTS t_article;

CREATE TABLE t_article (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '文章id',
  title varchar(50) NOT NULL COMMENT '文章标題',
  content longtext COMMENT '文章具體内容',
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO t_article VALUES ('1', 'SSM架構基礎教程', '從入門到精通...');
INSERT INTO t_article VALUES ('2', 'SPringBoot架構基礎教程', '從入門到精通...');

# 建立評論表t_comment并插入相關資料
DROP TABLE IF EXISTS t_comment;

CREATE TABLE t_comment (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '評論id',
  article_id int(11) NOT NULL COMMENT '關聯的文章id',
  content longtext COMMENT '評論内容',
  author varchar(200) DEFAULT        NULL COMMENT '評論使用者使用者名',
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO t_comment VALUES ('1', '1', '内容很詳細', '明明');
INSERT INTO t_comment VALUES ('2', '1', '已三連', '紅紅');
INSERT INTO t_comment VALUES ('3', '1', '很不錯', '小王');
INSERT INTO t_comment VALUES ('4', '1', '贊一個', '東東');
INSERT INTO t_comment VALUES ('5', '2', '内容全面', '方方');           

1.2 搭建項目

建立一個項目名稱為chapter03的Spring Initializr類型的項目。在Dependencies依賴中選擇SQL子產品中的MySQL和MyBatis依賴。

然後編寫資料庫表對應的實體類。在com.cy.domain包下,并在該包中編寫與資料庫表t_article和t_comment對應的實體類Comment和Article類。

(1) 在com.cy.domain包下建立Comment實體類。

package com.cy.domain;
/** 評論實體類 */
public class Comment {
    private Integer id;
    private Integer articleId;
    private String content;
    private String author;
    // Generate: Getter and Setter、toString()
}               

(2) 在com.cy.domain包下建立Article實體類。

package com.cy.domain;
import java.util.List;
/** 文章實體類 */
public class Article {
    private Integer id;
    private String title;
    private String content;
    private List<Comment> commentList;
    // Generate: Getter and Setter、toString()
}             

1.3 編寫配置檔案

首先在application.properties配置檔案中編寫對應的MySQL資料庫連接配接配置。

# MySQL資料庫連接配接配置
spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456           

然後對資料源類型選擇配置。Spring Boot 1.x版本預設使用的是tomcat.jdbc資料源,Sprng Boot 2.x版本預設使用的是Hikari資料源。如果使用其他資料源,還需要進行額外配置。這裡選擇使用阿裡巴巴的Druid資料源。在pom.xml檔案中添加Druid資料源的依賴啟動器。

<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid-spring-boot-starter</artifactId>
   <version>1.1.17</version>
</dependency>           

引入的druid-spring-boot-starter依賴,是阿裡巴巴為了迎合Spring Boot項目而适配的Druid資料源啟動器,當在pom.xml檔案中引入該啟動器後,不需要再進行其他額外配置,Spring Boot項目會自動識别配置Druid資料源。

上述配置的Druid資料源啟動器内部已經初始化了一些運作參數(例如initialSize、maxActive等),如果開發過程中需要修改第三方Druid的運作參數,則必須在全局配置檔案中修改。

# MySQL資料庫連接配接配置
spring.datasource.url=jdbc:mysql://localhost:3306/springbootdata?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=123456
# 添加并配置第三方資料源Druid
# 資料源類型
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 初始化連接配接數
spring.datasource.initialSize=20
# 最小空閑數
spring.datasource.minIdle=10
# 最大連接配接數
spring.datasource.maxActive=100           

在application.properties中添加上述配置後,會發現配置的initialSize、minIdle和maxActive屬性底色為黃色(IDEA開發工具中的顯示色)。這是因為在Spring Boot提供的資料源自動配置類org.springframework.boot.autoconfigure.jdbc.DataSourceProperties中,沒有與這些參數對應的預設屬性,是以這些設定的屬性值無法識别和生效。是以需要編寫一個自定義配置類,将配置檔案中的屬性注入到Druid資料源屬性中。

接着我們要在com.cy.config包下建立一個DataSourceConfig自定義配置類,對Druid資料源屬性值進行注入。

package com.cy.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource getDruid() {
        return new DruidDataSource();
    }
}           

2.使用注解的方式整合MyBatis

建立Mapper接口檔案。在com.cy.mapper包下建立一個用于對資料庫表t_comment資料操作的接口CommentMapper。

package com.cy.mapper;
import com.cy.domain.Comment;
import org.apache.ibatis.annotations.*;
@Mapper
public interface CommentMapper {
    @Select("SELECT * FROM t_comment WHERE id=#{id}")
    Comment findById(Integer id);
    @Insert("INSERT INTO t_comment(article_id,content,author) " +
            "values (#{articleId},#{content},#{author})")
    Integer insertComment(Comment comment);
    @Update("UPDATE t_comment SET content=#{content} WHERE id=#{id}")
    Integer updateComment(Comment comment);
    @Delete("DELETE FROM t_comment WHERE id=#{id}")
    Integer deleteComment(Integer id);
}           

說明:在對應的接口類上添加@Mapper注解,如果編寫的Mapper接口過多時,需要重複為每一個接口檔案添加@Mapper注解,為了避免這種麻煩,可以直接在Spring Boot項目啟動類上添加@MapperScan("xxx")注解,參數必須指定需要掃描的具體包名。

然後在com.cy測試包下建立MyBatisTests類,并在MyBatisTests類中引入CommentMapper接口,并對接口中方法進行測試。

package com.cy;
import com.cy.domain.Comment;
import com.cy.mapper.CommentMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class MyBatisTests {
    @Autowired
    private CommentMapper commentMapper;

    @Test
    public void findById() {
        Comment comment = commentMapper.findById(1);
        // Comment{id=1, articleId=null, content='内容很詳細', author='明明'}
        System.out.println(comment);
    }
    @Test
    public void insertComment() {
        Comment comment = new Comment();
        comment.setArticleId(2);
        comment.setContent("文章寫的很棒");
        comment.setAuthor("張三");
        commentMapper.insertComment(comment);
    }
    @Test
    public void updateComment() {
        Comment comment = new Comment();
        comment.setId(6);
        comment.setContent("贊贊贊");
        commentMapper.updateComment(comment);
    }
    @Test
    public void deleteComment() {
        commentMapper.deleteComment(6);
    }
}           

我們會發現控制台中查詢的Comment的articleId屬性值為null,沒有映射成功。這是因為編寫的實體類Comment中使用了駝峰命名方式将t_comment表中的article_id字段設計成了articleId屬性,是以無法正确映射查詢結果。為了解決上述由于駝峰命名方式造成的表字段值無法正确映射到類屬性的情況,可以在Spring Boot全局配置檔案application.properties中添加開啟駝峰命名比對映射配置。

# 開啟駝峰命名比對映射
mybatis.configuration.map-underscore-to-camel-case=true           

3.使用配置檔案的方式整合MyBatis

Spring Boot與MyBatis整合使用時,不僅支援注解方式,還支援XML配置檔案的方式。在com.cy.mapper包中建立一個操作資料表t_article的接口ArticleMapper。

package com.cy.mapper;
import com.cy.domain.Article;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ArticleMapper {
    Article findArticleById(Integer id);
    Integer updateArticle(Article article);
}           

建立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.cy.mapper.ArticleMapper">
    <resultMap id="articleWithComment" type="Article">
        <id property="id" column="id" />
        <result property="title" column="title" />
        <result property="content" column="content" />
        <collection property="commentList" ofType="Comment">
            <id property="id" column="id" />
            <result property="articleId" column="article_id" />
            <result property="content" column="content" />
            <result property="author" column="author" />
        </collection>
    </resultMap>
    <select id="findArticleById" resultMap="articleWithComment">
        SELECT a.*, c.*
        FROM t_article a, t_comment c
        WHERE a.id = c.article_id AND a.id = #{id}
    </select>
    <update id="updateArticle" parameterType="Article">
        UPDATE t_article
        <set>
            <if test="title !=null and title !=''">
                title=#{title},
            </if>
            <if test="content !=null and content !=''">
                content=#{content}
            </if>
        </set>
        WHERE id=#{id}
    </update>
</mapper>           

配置XML映射檔案路徑。在全局配置檔案application.properties中添加MyBatis映射檔案路徑的配置,同時需要添加實體類别名映射路徑。

# 配置MyBatis的XML配置檔案位置
mybatis.mapper-locations=classpath:mapper/*.xml
# 配置XML映射檔案中指定的實體類别名路徑
mybatis.type-aliases-package=com.cy.domain           

最後編寫單元測試進行接口方法測試,在測試類MyBatisTests中對接口方法進行測試。

@Autowired
private ArticleMapper articleMapper;
@Test
public void findArticleById() {
    Article article = articleMapper.findArticleById(1);
    System.out.println(article);
}
@Test
public void updateArticle() {
    Article article = new Article();
    article.setId(1);
    article.setTitle("SSM進階開發");
    article.setContent("進階進階内容");
    Integer rows = articleMapper.updateArticle(article);
    System.out.println(rows);
}           

繼續閱讀