Springboot 系列(十一)使用 Mybatis 訪問數據庫

1. Springboot mybatis 介紹

MyBatis 是一款優秀的持久層框架,它支持定製化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數獲取結果集的過程。MyBatis 可以使用簡單的 XML 或註解來配置和映射原生信息,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數據庫中的記錄。

關於 Mybatis 的基礎知識可以查詢官方文檔,十分的詳細。mybatis 官方文檔.

2. Springboot mybatis 依賴

本系列 Springboot 文章主要是 Springboot 的學習與分析,也因此只會試驗 Mybatis 在 Springboot 中的一些用法,關於 Mybatis 的基礎知識,還是需要自行學習的。 
創建 Springboot 項目不提,引入 maven 依賴,主要是 mybastis 核心依賴以及一個 mybatis xml 自動生成插件。依賴中的 druid 數據源部分,可以參考系列文章第九篇。

 <dependencies>
        <!-- Spring Boot web 開發整合 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-json</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 阿里 fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>

        <!-- Lombok 工具 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- 導入配置文件處理器,在配置springboot相關文件時候會有提示 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- 單元測試 -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>

        <!-- Druid 數據源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!-- mybatis mapper自動生成插件 -->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.7</version>
            <scope>compile</scope>
            <optional>true</optional>
        </dependency>

        <!--添加數據庫鏈接 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
    </dependencies>

3. Springboot mybatis 配置

關於 Druid 數據源的配置不再說明,可以參考系列文章第九篇。配置中主要配置了項目編碼、數據源信息、durid 數據源和 mybatis 的 mapper 位置以及 mybatis 映射別名的包路徑。

############################################################
# 服務啓動端口號
server.port=8080
spring.profiles.active=dev

# 編碼
server.tomcat.uri-encoding=utf-8
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
############################################################
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123

# 使用 druid 數據源
spring.datasource.type: com.alibaba.druid.pool.DruidDataSource
spring.datasource.initialSize: 5
spring.datasource.minIdle: 5
spring.datasource.maxActive: 20
spring.datasource.maxWait: 60000
spring.datasource.timeBetweenEvictionRunsMillis: 60000
spring.datasource.minEvictableIdleTimeMillis: 300000
spring.datasource.validationQuery: SELECT 1 FROM DUAL
spring.datasource.testWhileIdle: true
spring.datasource.testOnBorrow: false
spring.datasource.testOnReturn: false
spring.datasource.poolPreparedStatements: true
spring.datasource.filters: stat
spring.datasource.maxPoolPreparedStatementPerConnectionSize: 20
spring.datasource.useGlobalDataSourceStat: true
spring.datasource.connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

# mybatis
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=net.codingme.boot.domain

4. Springboot mybatis 編碼

mybatis 是半 ORM 框架,它通過 XML 描述符或者註解把 POJO 對象與 SQL 信息關聯起來,也因爲是和 SQL 關聯起來,使用 mybatis 可以充分的利用數據的各種功能以及強大的 SQL 語句。也可以發發現使用 mybatis 至少應該建立 POJO 對象和 SQL 關聯信息以及編寫相關操作代碼。

4.1. 數據庫準備

既然是持久層框架,先準備一個用戶實驗操作的數據表。上一個步驟中有配置數據庫信息爲 springboot。

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/springboot

因此在 mysql 數據庫的 springboot 庫中創建表 book 用於演示。

CREATE TABLE `book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `author` varchar(255) DEFAULT NULL COMMENT '書籍作者',
  `name` varchar(255) DEFAULT NULL COMMENT '書籍名稱',
  `price` float NOT NULL COMMENT '書籍價格',
  `create_time` datetime NOT NULL COMMENT '創建時間',
  `description` varchar(255) DEFAULT NULL COMMENT '書籍描述',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;

增加測試數據。

INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (2, '金庸', '笑傲江湖', 12, '2018-09-01 10:10:12', '是作家金庸創作的一部長篇武俠小說');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (3, '羅貫中', '三國演義', 22, '2018-09-01 10:10:16', '是作家羅貫中創作的一部長篇歷史小說');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (4, '吳承恩', '西遊記', 17, '2018-09-01 10:10:19', '是作家吳承恩創作的一部長篇小說');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (5, '金庸1535767819284', '笑傲江湖1535767819284', 43, '2018-09-01 10:10:19', '是作家金庸創作的一部長篇武俠小說1535767819284');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (6, '金庸1535767819679', '笑傲江湖1535767819679', 24, '2018-09-01 10:10:20', '是作家金庸創作的一部長篇武俠小說1535767819679');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (7, '羅貫中1535769035138', '三國演義1535769035138', 20, '2018-09-01 10:30:35', '是羅貫中創作的一部小說1535769035138');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (8, '金庸1535783611785', '笑傲江湖1535783611785', 30, '2018-09-01 14:33:32', '是作家金庸創作的一部長篇武俠小說1535783611785');

4.2. 自動生成插件

傳統的 mybatis 開發過程需要依照數據表新建大量的 POJO 類,然後在編寫響應的增刪改查接口,繼而編寫增刪改查對應的 XML 文件。過程無趣且有重複勞動,因此產生了一個自動生成工具,可以通過 JDBC 連接到數據庫,自動的創建 POJO、操作接口、XML 文件。

在引入依賴的時候已經引入了自動生成插件,也就是 mybatis-generator-core

接着在項目根目錄下創建自動生成配置文件,主要配置數據庫信息和要生成的表已經生成的代碼存放位置。

在之前作者也介紹過,可以參考博客文章使用MyBatis Generator自動生成Model、Dao、Mapper相關代碼。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <context id="MysqlContext" targetRuntime="MyBatis3Simple" defaultModelType="flat">
        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=utf-8&amp;serverTimezone=GMT%2B8&amp;nullCatalogMeansCurrent=true"
                        userId="root"
                        password="123">
        </jdbcConnection>

        <!-- 對於生成的pojo所在包 -->
        <javaModelGenerator targetPackage="net.codingme.boot.domain" targetProject="src/main/java"/>

        <!-- 對於生成的mapper所在目錄 -->
        <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"/>

        <!-- 配置mapper對應的java映射 -->
        <javaClientGenerator targetPackage="net.codingme.boot.domain.mapper" targetProject="src/main/java"
                             type="XMLMAPPER"/>

        <!-- 要生成那些表(更改tableName和domainObjectName就可以) -->
        <table tableName="book" domainObjectName="Book" enableCountByExample="true"
               enableUpdateByExample="true" enableUpdateByPrimaryKey="true"
               selectByExampleQueryId="true" enableDeleteByPrimaryKey="true"
               enableSelectByPrimaryKey="true" enableSelectByExample="true"
        ></table>

    </context>
</generatorConfiguration>

寫好配置文件之後,還需要寫一個啓動程序,用於加載配置文件,運行就可以生成相關配置。

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.util.ArrayList;

/**
 * <p>
 * Mybatis generator的逆向生成工具類
 *
 * @Author SpringRroot
 * @Date 2019/11/30 22:57
 */
public class MybatisGenerator {

    public void generator() throws Exception {
        ArrayList<String> warnings = new ArrayList<>();
        boolean overwrite = true;
        // 指定你想工程配置文件
        File configFile = new File("generatorConfig.xml");
        System.out.println(configFile.getAbsolutePath());
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
    }

    public static void main(String[] args) throws Exception {
        MybatisGenerator mybatisGenerator = new MybatisGenerator();
        mybatisGenerator.generator();
    }
}

生成的文件如下圖。

查看生成的接口以及 XML 映射文件可以發現已經自動生成了常用的幾個方法。

  1. deleteByPrimaryKey
  2. insert
  3. updateByPrimaryKey
  4. selectByPrimaryKey
  5. selectAll

4.3. 註解配置方式

Mybatis 同樣支持註解的方式配置映射關係,使用註解可以替代 XML 的配置,寫一個簡單的註解例子。在剛纔生成的 BookMapper.java 中增加一個根據作者名稱查詢的方法,並映射字段對應的屬性。

// 添加 @Repository 註解,這樣在使用 @Autowired 引入的時候不會報橫線
@Repository
public interface BookMapper {
     /**
     * 註解方式配置映射
     *
     * @param author
     * @return
     * @Results 字段和屬性映射關係
     * @Select 查詢語句
     */
    @Results({
            @Result(property = "id", column = "ids"),
            @Result(property = "name", column = "name"),
            @Result(property = "author", column = "authors"),
            @Result(property = "createTime", column = "create_time")
    })
    @Select("select id as ids, author as authors, name, price, create_time, description from book where author = #{author}")
    List<Book> selectByAuthor(@Param("author") String author);
    // 省略下面自動生成代碼

5. Springboot mybatis 測試

正常情況下會在項目中的業務層 service 包下創建接口和類然後通過註解引入使用。

@Autowired
private BookMapper bookMapper;

我們只是實驗,沒有這樣寫一套的必要,只要能確保 BookMapper 可以正常注入使用就好了。因此創建測試類進行測試。

在生成的(也可以完全手寫測試方法)測試類中添加測試方法進行測試。

@RunWith(SpringRunner.class)
@SpringBootTest
public class BookMapperTest {

    @Autowired
    private BookMapper bookMapper;

    @Test
    public void testSelectAll() {
        List<Book> bookList = bookMapper.selectAll();
        Assert.assertNotNull(bookList);
        bookList.forEach((book) -> System.out.println(book));
    }


    @Test
    public void testSelectByAuthro() {
        List<Book> bookList = bookMapper.selectByAuthor("金庸");
        Assert.assertNotNull(bookList);
        bookList.forEach((book) -> System.out.println(book));
    }

    @Test
    public void testSelectByPrimaryKey() {
        Book book = bookMapper.selectByPrimaryKey(2);
        Assert.assertNotNull(book);
        System.out.println(book);
    }

    public void testDeleteByPrimaryKey() {
        int primaryKey = bookMapper.deleteByPrimaryKey(8);
        Assert.assertNotEquals(0, primaryKey);
        System.out.println(primaryKey);
    }

}

爲了觀察查詢接口 book 的信息輸出,重寫 Book 類的 toString 方法,然後運行單元測試。


可以發現測試全部通過。結果正常。

發佈了96 篇原創文章 · 獲贊 162 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章