SpringBoot集成MyBatis 原

SpringBoot集成MyBatis

ORM 框架是什麼

Object Relational Mapping,簡稱 ORM,對象關係映射模式是一種爲了解決面向對象與關係數據庫存在的互不匹配的現象技術。簡單的說,ORM 是通過使用描述對象和數據庫之間映射的元數據,將程序中的對象自動持久化到關係數據庫中。

爲什麼需要 ORM

當開發一個應用程序的時候(不使用 O/R Mapping),你可能會寫不少數據訪問層的代碼,用來從數據庫保存、刪除、讀取對象信息等。在 數據訪問層,DAL (Data Access Layer),中寫了很多的方法來讀取對象數據、改變狀態對象等任務,而這些代碼寫起來總是重複的。 針對這些問題 ORM 提供瞭解決方案,簡化了將程序中的對象持久化到關係數據庫中的操作,讓程序員完全地面向對象編程。

MyBatis 介紹

歷史

MyBatis 就是一款標準的 ORM 框架,被廣泛的應用於各企業開發中。MyBatis 本是 Apache 的一個開源項目 IBatis,2010 年這個項目由 Apache Software Foundation 遷移到了 Google Code,並且改名爲 MyBatis,2013 年 11 月又遷移到 Github 上。

作用

MyBatis 支持普通 SQL 查詢,存儲過程和高級映射的優秀持久層框架。MyBatis 消除了幾乎所有的 JDBC 代碼和參數的手工設置以及對結果集的檢索封裝。MaBatis 可以使用簡單的 XML 或註解用於配置和原始映射。將接口和 Java 的 POJO(Plain Old Java Objects,普通的 Java 對象)映射成數據庫中的記錄。

特點

1.優點

(1)SQL 被統一提取出來,便於統一管理和優化

(2)SQL 和代碼解耦,將業務邏輯和數據訪問邏輯分離,使系統的設計更清晰,更易維護,更易單元測試

(3)提供映射標籤,支持對象與數據庫的 ORM 字段關係映射

(4)提供對象關係映射標籤,支持對象關係組件維護

(5)靈活書寫動態 SQL,支持各種條件來動態生成不同的 SQL

2.缺點

(1)編寫 SQL 語句時工作量很大,尤其是字段多、關聯表多時,更是如此

(2)SQL 語句依賴於數據庫,導致數據庫移植性差

MyBatis 幾個重要的概念:

Mapper配置:基於 XML 的 Mapper 配置文件和基於 Java 註解的 MyBatis 註解來實現。

Mapper接口:即DAO(Data Access Object )數據訪問對象是一個面向對象的數據庫接口,這類 Mapper 接口是指自行定義的一個數據操作接口,MyBatis 會自動爲 Mapper 接口創建動態代理對象。Mapper 接口的方法通常與 Mapper 配置文件中的 select、insert、update、delete 等 XML 節點存在一一對應關係。

Executor: MyBatis 中所有的 Mapper 語句的執行都是通過 Executor 進行的,Executor 是 MyBatis 的一個核心接口。

SqlSession: SqlSession 是 MyBatis 的關鍵對象,是執行持久化操作的獨享,類似於 JDBC 中的 Connection,SqlSession 對象完全包含以數據庫爲背景的所有執行 SQL 操作的方法,它的底層封裝了 JDBC 連接,可以用 SqlSession 實例來直接執行被映射的 SQL 語句。

SqlSessionFactory: SqlSessionFactory 是 MyBatis 的關鍵對象,它是單個數據庫映射關係經過編譯後的內存鏡像。SqlSessionFactory 對象的實例可以通過 SqlSessionFactoryBuilder 對象類獲得,而 SqlSessionFactoryBuilder 則可以從 XML 配置文件或一個預先定製的 Configuration 的實例構建出。

MyBatis 的工作流程如下: MyBatis工作流程圖

首先加載 Mapper 配置的 SQL 映射文件,或者是註解的相關 SQL 內容。

創建會話工廠,MyBatis 通過讀取配置文件的信息來構造出會話工廠(SqlSessionFactory)。

創建會話。根據會話工廠,MyBatis 就可以通過它來創建會話對象(SqlSession)。會話對象是一個接口,該接口中包含了對數據庫操作的增刪改查方法。

創建執行器。因爲會話對象本身不能直接操作數據庫,所以它使用了一個叫做數據庫執行器(Executor)的接口來幫它執行操作。

封裝 SQL 對象。在這一步,執行器將待處理的 SQL 信息封裝到一個對象中(MappedStatement),該對象包括 SQL 語句、輸入參數映射信息(Java 簡單類型、HashMap 或 POJO)和輸出結果映射信息(Java 簡單類型、HashMap 或 POJO)。

操作數據庫。擁有了執行器和 SQL 信息封裝對象就使用它們訪問數據庫了,最後再返回操作結果,結束流程。

MyBatis-Spring-Boot-Starter

MyBatis-Spring-Boot-Starter 是 MyBatis 幫助我們快速集成 Spring Boot 提供的一個組件包。

使用這個組件可以做到以下幾點:

構建獨立的應用

幾乎可以零配置

需要很少的 XML 配置

mybatis-spring-boot-starter主要提供了兩種解決方案,一種是簡化後的 XML 配置版,另外一種是使用註解解決一切問題。

XML 版本

XML 版本保持映射文件的老傳統,優化主要體現在不需要實現 Dao 的實現層,系統會自動根據方法名在映射文件中找到對應的 SQL。

一、相關配置

1.依賴包配置

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
    <version></version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.6</version>
</dependency>

2.application 配置

application.property配置:

#配置 mybatis-config.xml 路徑,mybatis-config.xml 中配置 MyBatis 基礎屬性。
mybatis.config-locations=classpath:mybatis/mybatis-config.xml
#配置 Mapper 對應的 XML 文件路徑
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
#配置項目中實體類包路徑
mybatis.type-aliases-package=com.grit.learning.entity
#數據源配置信息
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/db_test?useUnicode=true&characterEncoding=utf-8
spring.datasource.username = root
spring.datasource.password = root

Spring Boot 啓動時數據源會自動注入到 SqlSessionFactory 中,使用 SqlSessionFactory 構建 SqlSessionFactory,再自動注入到 Mapper 中,最後我們直接使用 Mapper 即可。

二、啓動類上添加註解

在啓動類中添加對 Mapper 包掃描@MapperScan,Spring Boot 啓動的時候會自動加載包路徑下的 Mapper。

@SpringBootApplication
@MapperScan("com.grit.learning.mapper")
public class MybatisInSpringbootApplication {

	public static void main(String[] args) {
		SpringApplication.run(MybatisInSpringbootApplication.class, args);
	}
}

或者直接在 Mapper 類上面添加註解@Mapper,建議使用上面那種,不然每個 Mapper 加個註解會很麻煩。

三、開發 SQL

(1)MyBatis 公共屬性

mybatis-config.xml,主要配置常用的 typeAliases,設置類型別名爲 Java 類型設置一個短的名字。它只和 XML 配置有關,存在的意義僅在於用來減少類完全限定名的冗餘。

<configuration>
    <typeAliases>
        <typeAlias alias="Integer" type="java.lang.Integer" />
        <typeAlias alias="Long" type="java.lang.Long" />
        <typeAlias alias="HashMap" type="java.util.HashMap" />
        <typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" />
        <typeAlias alias="ArrayList" type="java.util.ArrayList" />
        <typeAlias alias="LinkedList" type="java.util.LinkedList" />
    </typeAliases>
</configuration>

這樣在使用 Mapper.xml 的時候,需要引入可以直接這樣寫:

resultType="Integer" 
//或者
parameterType="Long"

(2)添加 User 的映射文件

指明對應文件的 Mapper 類地址:

<mapper namespace="com.grit.learning.mapper.UserMapper" >

配置表結構和類的對應關係:

 <resultMap id="BaseResultMap" type="com.grit.learning.entity.UserEntity" >
     <id column="id" property="id" jdbcType="BIGINT" />
     <result column="userName" property="userName" jdbcType="VARCHAR" />
     <result column="passWord" property="passWord" jdbcType="VARCHAR" />
     <result column="user_sex" property="userSex"                javaType="com.grit.learning.enums.UserSexEnum"/>
     <result column="nick_name" property="nickName" jdbcType="VARCHAR" />
</resultMap>

這裏爲了更好的貼近工作情況,故意將類的兩個字段和數據庫字段設置爲不一致,並且有一個使用了枚舉。使用枚舉有一個非常大的優點,插入此屬性的數據會自動進行校驗,如果不是枚舉的內容會報錯

寫具體的 SQL 語句,比如這樣:

<select id="getAll" resultMap="BaseResultMap">
   SELECT 
   *
   FROM users
</select>

MyBatisXML 有一個特點是可以複用 XML,比如公用的一些 XML 片段可以提取出來,在其他 SQL 中去引用,如:

<sql id="Base_Column_List" >
    id, userName, passWord, user_sex, nick_name
</sql>

<select id="getAll" resultMap="BaseResultMap"  >
   SELECT 
   <include refid="Base_Column_List" />
   FROM users
</select>  

這個例子就是,上面定義了需要查詢的表字段,下面 SQL 使用 include 引入,避免了寫太多重複的配置內容。

下面就是常用的增刪改查的例子:

    <select id="getOne" parameterType="Long" resultMap="BaseResultMap" >
        SELECT 
       <include refid="Base_Column_List" />
	   FROM users
	   WHERE id = #{id}
    </select>

    <insert id="insert" parameterType="com.grit.learning.entity.UserEntity" >
       INSERT INTO 
       		users
       		(userName,passWord,user_sex) 
       	VALUES
       		(#{userName}, #{passWord}, #{userSex})
    </insert>
    
    <update id="update" parameterType="com.grit.learning.entity.UserEntity" >
       UPDATE 
       		users 
       SET 
       	<if test="userName != null">userName = #{userName},</if>
       	<if test="passWord != null">passWord = #{passWord},</if>
       	nick_name = #{nickName}
       WHERE 
       		id = #{id}
    </update>
    
    <delete id="delete" parameterType="Long" >
       DELETE FROM
       		 users 
       WHERE 
       		 id =#{id}
    </delete>

上面 update 的 SQL 使用了if標籤,可以根據不同的條件動態的生產 SQL,這就是 MyBatis 最大的特點。

四、編寫 Dao 層的代碼

public interface UserMapper {

    List<UserEntity> getAll();

    UserEntity getOne(Long id);

    void insert(UserEntity user);

    void update(UserEntity user);

    void delete(Long id);
}

注意:這裏的方法名需要和 XML 配置中的 id 屬性一致,不然會找不到方法去對應執行的 SQL。

五、測試使用

按照 Spring 一貫使用形式,直接將對應的 Mapper 注入即可。

[@Resource](https://my.oschina.net/u/929718)
private UserMapper userMapper;

接下來直接使用 userMapper 進行數據庫操作即可。

@Test
public void testUser()  {
    //增加
    userMapper.insert(new UserEntity("aa", "a123456", UserSexEnum.MAN));
    //刪除
    int count=userMapper.delete(29l);
    //修改
    userMapper.update(user);
    //查詢
    List<UserEntity> users = userMapper.getAll();
    UserEntity user = userMapper.getOne(1l);
}

在示例代碼中,寫了兩份的使用,一個是 Test,一個在 Controller 層,方便查看。

六、分頁查詢

多條件分頁查詢是我們在實際工作中最常使用的一個功能,MyBatis 也特別擅長處理這類的問題。在實際工作中,會對分頁進行簡單的封裝,方便前端使用。另外在 Web 開發規範使用中,一般 Web 層的參數會以 param 爲後綴的對象進行傳參,以 entity 爲後綴的對象負責和數據庫打交道,以 result 結尾的實體類一般用於封裝返回的數據。

下面給大家以 User 多條件分頁查詢爲例進行講解:

先定義一個分頁的基礎類:

public class PageParam {
    private int beginLine;                   //起始行
    private Integer pageSize = 3;
    private Integer currentPage=0;        // 當前頁
    //getter setter 省略
    public int getBeginLine() {
        return pageSize*currentPage;        //自動計算起始行
    }
}

默認每頁 3 條記錄,可以根據前端傳參進行修改。

user 的查詢條件參數類繼承分頁基礎類:

public class UserParam extends PageParam{
    private String userName;
    private String userSex;
    //getter setter省略
}

接下來配置具體的 SQL,先將查詢條件提取出來。

<sql id="Base_Where_List">
    <if test="userName != null  and userName != ''">
        and userName = #{userName}
    </if>
    <if test="userSex != null and userSex != ''">
        and user_sex = #{userSex}
    </if>
</sql>

從對象 UserParam 中獲取分頁信息和查詢條件,最後進行組合。

 <select id="getList" resultMap="BaseResultMap" parameterType="com.grit.learning.param.UserParam">
        select
        <include refid="Base_Column_List" />
        from users
        where 1=1
        <include refid="Base_Where_List" />
        order by id desc
        limit #{beginLine} , #{pageSize}
 </select>

前端需要展示總共的頁碼,因此需要統計出查詢結果的總數。

<select id="getCount" resultType="Integer" parameterType="com.grit.learning.param.UserParam">
        select
        count(1)
        from users
        where 1=1
        <include refid="Base_Where_List" />
 </select>

Mapper 中定義的兩個方法和配置文件相互對應。

public interface UserMapper {
    List<UserEntity> getList(UserParam userParam);
    int getCount(UserParam userParam);
}

具體使用如下:

@Test
public void testPage() {
    UserParam userParam=new UserParam();
    userParam.setUserSex("WOMAN");
    userParam.setCurrentPage(1);
    List<UserEntity> users=userMapper.getList(userParam);
    long count=userMapper.getCount(userParam);
    Page page = new Page(userParam,count,users);
    System.out.println(page);
}

實際使用中,只需要傳入 CurrentPage 參數即可,默認 0 就是第一頁,傳 1 就是第二頁的內容,最後將結果封裝爲 Page 返回給前端。

public class Page<E> implements Serializable {
    private int currentPage = 0; //當前頁數
    private long totalPage;       //總頁數
    private long totalNumber;    //總記錄數
    private List<E> list;        //數據集
}

Page 將分頁信息和數據信息進行封裝,方便前端顯示第幾頁、總條數和數據。這樣常用的場景就演示完了。

無配置文件註解版

該部分代碼,如有感興趣的同學請下載源碼來研究對比

github地址: https://github.com/Grit-tan/mybatisForAnnotation-in-springboot

如何選擇

兩種模式各有特點,註解版適合簡單快速的模式,在微服務架構中,一般微服務都有自己對應的數據庫,多表連接查詢的需求會大大的降低,會越來越適合註解版。XML 模式比適合大型項目,可以靈活的動態生成 SQL,方便調整 SQL,也有痛痛快快、洋洋灑灑地寫 SQL 的感覺。在具體開發過程中,根據公司業務和團隊技術基礎進行選型即可。

github地址: https://github.com/Grit-tan/mybatis-in-springboot

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章