30分鐘入門MyBatis

本文旨在用最通俗的語言講述最枯燥的基本知識

當項目框架SSH(spring Struts hibernate)日落西山時,SSM(spring SpringMVC、MyBatis)就大行其道,大部分項目都漸漸轉至SSM,所以mybatis也成了Java程序員的必學之術,本文就mybatis的語法作一次小小的總結,旨在讓讀者用最少的時間學會使用MyBatis。java

文章提綱:mysql

  1. 什麼是MyBatis
  2. MyBatis的引入
  3. MyBatis的初始化配置
  4. MyBatis的SQL語法
  5. 運行原理和實操一波

1. 什麼是MyBatis

MyBatis的前身是Apache的一個開源項目ibatis,後來遷移到Google code就更名爲MyBatis。程序員

用網上已經說爛了的話來講就是:spring

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

2. MyBatis的引入

  1. 若是是傳統的的項目,則直接下載相應jar包引入到項目中便可,下載地址爲:
http://central.maven.org/maven2/org/mybatis/mybatis/3.4.6/mybatis-3.4.6.jar
  1. 若是爲maven構建的項目,則只須要在pom.xml中加入如下依賴而後reimport一下便可:
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>
  1. 若是是gradle構建的項目,則只須要在配置中添加如下代碼:
// https://mvnrepository.com/artifact/org.mybatis/mybatis
compile group: 'org.mybatis', name: 'mybatis', version: '3.4.6'

3. MyBatis的配置和初始化

在引入mybatis以後,接下來須要學習的mybatis的配置,雖然如今流行的框架像springboot等已經不須要用XML方式進行配置,但做爲一名新手,咱們仍是須要學習一些關於mybatis的配置的解釋,這樣有助於咱們理解mybatis的原理。
mybatis的基本配置:數據庫

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--properties用於定義一些屬性變量,以便在配置文件中調用-->
    <properties>
        <!--定義一個變量爲driver的屬性,在下面就能夠用${driver}來得到其屬性值-->
        <property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://10.0.0.111/test"></property>
    </properties>
    <!--定義不一樣環境下的配置,便於區分生產、測試等環節的配置-->
    <environments default="development">
       <!--定義一個環境下的配置-->
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="root"/>
                <property name="password" value="1111"/>
            </dataSource>
        </environment>
    </environments>
    <!--用於設置mapper文件的引入-->
    <mappers>
        <!--resource方式引入mapper文件-->
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

這是一個標準的mybatis的配置文件,不少狀況下,這個配置已經,可是爲了在之後的使用有更好的認識,下面講解配置文件中configuration標籤下的經常使用子標籤:編程

  1. properties標籤:用於定義一些通用屬性,便於配置文件中使用
  2. settings標籤:用於設置一些改變MyBatis運行時行爲的配置
  3. environments標籤:用於配置成適應多種環境
  4. mappers標籤:用於mapper映射器的設置

下面分別對每一個標籤作簡單講解:設計模式

1.properties標籤

當咱們須要把一些值做爲一個變量被配置中使用時,就能夠在properties標籤下增長一個property標籤,其中屬性name是指變量名稱,屬性value是值,如:緩存

<properties>
        <property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
 </property>

定義好以後,就能夠在配置文件中使用了,如:springboot

<dataSource type="POOLED">
   <property name="driver" value="${driver}"/>
</dataSource>

1.settings標籤

settings標籤中的每個setting都是用於調整mybatis的運行行爲,咱們在須要使用其中某些setting時加入便可,其經常使用的配置以及各個setting的解釋以下:

<settings>
  #設置配置文件中的全部映射器已經配置的任何緩存,默認false。
  <setting name="cacheEnabled" value="true"/>
  #延遲加載的全局開關。當開啓時,全部關聯對象都會延遲加載,默認爲false
  <setting name="lazyLoadingEnabled" value="true"/>
  #是否容許單一語句返回多結果集,默認爲true
  <setting name="multipleResultSetsEnabled" value="true"/>
  #是否使用列標籤代替列名,默認爲true
  <setting name="useColumnLabel" value="true"/>
  #是否容許JDBC支持自動生成主鍵,默認爲false
  <setting name="useGeneratedKeys" value="false"/>
  #指定 MyBatis 應如何自動映射列到字段或屬性
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  #指定發現自動映射目標未知列(或者未知屬性類型)的行爲,默認NONE
  #NONE: 不作任何反應
  #WARNING: 輸出提醒日誌
  #FAILING: 映射失敗 (拋出 SqlSessionException)
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  #配置默認的執行器。默認爲SIMPLE
  #SIMPLE 就是普通的執行器;
  #REUSE 執行器會重用預處理語句; 
  #BATCH 執行器將重用語句並執行批量更新
  <setting name="defaultExecutorType" value="SIMPLE"/>
  #設置超時時間,它決定驅動等待數據庫響應的秒數。 
  <setting name="defaultStatementTimeout" value="25"/>
  #爲驅動的結果集獲取數量(fetchSize)設置一個提示值  
  <setting name="defaultFetchSize" value="100"/>
  #是否容許在嵌套語句中使用分頁。若是容許使用則設置爲false。
  <setting name="safeRowBoundsEnabled" value="false"/>
  #是否開啓自動駝峯命名規則(camel case)映射,默認爲false
  <setting name="mapUnderscoreToCamelCase" value="false"/>
</settings>

3. environments

environments是爲了配置多環境數據源而生,在咱們定義好了各類環境以後,只須要在代碼中設置從哪一個環境中加載數據源便可,或者修改environments標籤中的default也能夠達到切換環境的效果。
environments的基本配置以下:

<environments default="development">
  #定義一個名稱爲development的環境配置
  <environment id="development">
    #設置事務管理器的類型,有JDBC和MANAGED梁總
    <transactionManager type="JDBC">
      <property name="..." value="..."/>
    </transactionManager>
    #數據源設置
    <dataSource type="POOLED">
      <property name="driver" value="${driver}"/>
      <property name="url" value="${url}"/>
      <property name="username" value="${username}"/>
      <property name="password" value="${password}"/>
    </dataSource>
  </environment>
</environments>

當咱們須要增長一個環境配置時,只須要複製粘貼一份environment,修改其中屬性的值便可。

4.mappers

mappers標籤其實是用於高速mybatis從哪找到咱們寫好的SQL語句,也就是映射文件。當咱們寫好一個表對應的mapper.xml時,咱們只須要在mappers下增長一個mapper便可。

mappers查找mapper的方式有多種:

1. 根據mapper.xml文件定位:

這些mapper.xml在resources中的某個文件夾xxx中,則用resource屬性設置

<mappers>
<mapper resource="xxx/AMapper.xml"/>
<mapper resource="xxx/BMapper.xml"/>
</mappers>
2. 根據映射器接口實現類的徹底限定類名:

當咱們在這些mapper.xml設置好了namespace以後,咱們能夠經過映射器接口實現類的全路徑類來設置,如在AMapper.xml設置namespace爲com.xxx.dao.AMapper類以後,咱們在這裏可使用class屬性指定查找的mapper,但前提是:
AMapper.xml和AMapper.java必須在同一個包下。

<mappers>
<mapper class ="com.xxx.dao.AMapper"/>
<mapper class ="com.xxx.dao.BMapper"/>
</mappers>
3. 包映射

有人會說,若是咱們表有不少,這樣一行一行的寫不是很費勁嗎,mybatis爲了便於使用,提供了package的方式引入映射器,但前提
全部的mapper.xml和mapper.java必須在同一個包下。

<mappers>
  <package name="org.xxx.dao"/>
</mappers>

4. URL映射:

若是你的mapper不在項目中,而是放到了其餘文件內,mybatis提供了經過URL的方式引入mapper.xml。

<mappers>
  <mapper url="C:///test/mappers/AMapper.xml"/>
  <mapper url="C:///test/mappers/BMapper.xml"/>
</mappers>

5. MyBatis的SQL語法

在現有的框架下編寫代碼,多數狀況下都不須要理會mybatis底層的東西,而大量的工做都集中在編寫mapper文件上。所以學會在mybatis下編寫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.xxx.dao.XxxMapper">
</mapper>

能夠看出,一個mapper文件的根結構是mapper標籤開始,而mapper標籤中的namespace有什麼用呢?他應該怎麼寫?

咱們知道,有一種編程思想叫作面向接口編程,就是把業務需求中具體邏輯實現和接口分開,對外只暴露接口,經過接口實現業務。而在業務需求變化時,僅須要修改實現類,而不須要變更現有的對接代碼,下降對系統的影響。

而mybatis正是基於這樣的思想,在namespace中指定該mapper對應的接口以後,不須要編寫接口實現類,mybatis會經過該綁定自動幫你找到對應要執行的SQL語句。

如:在com.xxx.dao中建立一個XxxMapper.java的接口,須要編寫一根據用戶查詢用戶信息的方法。

package com.xxx.dao;
public interface XxxMapper  {
  //根據姓名查詢一條用戶信息
  Map selectUserByName(@Param("name") String name);
}

此時咱們就能夠在mapper.xml中設置namespace對應到上面的接口來:

<?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.xxx.dao.XxxMapper">
 <select id="selectUserByName" parameterType="String" resultType="hashmap">
  select * from user where name = #{name}
</select>
</mapper>

而在具體的業務實現類中,則是這樣使用的:

@Service
public class XxxServiceImpl implements CustomerInfoService {
    @Resource
    private  XxxMapper xxxMapper=null;
    @Override
    public Map getUser(String name) {
        return xxxMapper.selectUserByName(name);
    }
}

能夠看出,從編寫SQL語句到最終業務調用SQL語句的過程當中,咱們並無給XxxMapper接口編寫任何的實現類,這就是基於接口編程的思想,mybatis已經把這些事情都處理好了,咱們只須要在namespace中把SQL映射文件和接口類對應起來,就可使用了。

知道根節點mapper怎麼設置以後,接下來咱們須要學習如何在mapper節點裏編寫SQL語句,在mapper標籤後,mybatis提供了不少語義化的標籤以便於咱們編寫SQL語句和配置映射文件,下面是幾個很是經常使用子標籤:

1. select:用於編寫查詢語句的標籤
2. update:用於編寫update語句的標籤
3. insert:用於編寫insert語句的標籤
4. delete:用於編寫delete語句的標籤
5. sql:編寫語句塊的標籤,可被其它語句引用
6. resultMap:定義數據庫結果和實體屬性的映射關係

這些標籤都是咱們在編寫SQL語句中的必備標籤,下面一一描述他們的使用。

1. select標籤

在一個項目中,大部分功能都涉及到查詢,所以mybatis也爲select元素配備了很是多的屬性,一下僅列出最經常使用的幾個屬性以及做用解釋:

<select
  #必填,惟一標識符,和mapper接口中的方法一一對應
  id="selectUser"
  #選填,默認值爲 unset,用於傳入參數的類型設置
  parameterType="String"
  #選填,語句查詢結果返回的指望類型,resultType 和 resultMap不能同時使用
  resultType="HashMap"
  #選填,語句查詢結果返回的數據集,能夠對應實體類和和resultMap定義的ID。
  resultMap="com.xxx.entity.User"
  #是否清除緩存,爲true時本地緩存和二級緩存都會被清除
  flushCache="false"
  #是否啓用緩存,爲true時查詢結果會被放入二級緩存
  useCache="true"  >

 #SQL語句編寫....

 </select>

2. update標籤

<update
  #必填,惟一標識符,和mapper接口中的方法一一對應
  id="updateUser"
  #選填,默認值爲 unset,用於傳入參數的類型設置
  parameterType="com.xxx.entity.User"
  #是否清除緩存,爲true時本地緩存和二級緩存都會被清除
  flushCache="true">

 #編寫update的SQL語句...

</update>

3. insert標籤

<insert
  #必填,惟一標識符,和mapper接口中的方法一一對應
  id="updateUser"
  #選填,默認值爲 unset,用於傳入參數的類型設置
  parameterType="com.xxx.entity.User"
  #是否清除緩存,爲true時本地緩存和二級緩存都會被清除
  flushCache="true"
  #是否取出由數據庫內部生成的主鍵,默認爲false
   useGeneratedKeys="false"  
   #選填,設置了以後,會經過getGeneratedKeys的返回值或者經過 insert語句的selectKey子元素設置它的鍵值。
   keyProperty="id"
  >

 #編寫insert的SQL語句...

</insert>

4. delete標籤

<delete
  #必填,惟一標識符,和mapper接口中的方法一一對應
  id="updateUser"
  #選填,默認值爲 unset,用於傳入參數的類型設置
  parameterType="com.xxx.entity.User"
  #是否清除緩存,爲true時本地緩存和二級緩存都會被清除
  flushCache="true">

 #編寫delete的SQL語句...

</delete>

5. sql標籤

SQL節點用來編寫那些能夠被重用的SQL代碼段,當咱們用SQL編寫好一個代碼段以後,就能夠在其餘語句使用。

咱們都知道,在寫滿了SQL以後,若是要修改表名,是一件很痛苦的事情,由於表名都寫到了SQL語句中了,可是在mybatis中,咱們能夠利用sql標籤來定義好表名,若是在全部的SQL中引入這個代碼塊便可:

<sql id="TABLE_NAME">user</sql>

#在語句中用include的方式把表名動態化
<select id="selectUserByName">
select * from 
<include refid="TABLE_NAME" />
 where name = #{name}
</select>

相似的用法還有很是多,好比把查詢字段一致的能夠用sql塊統必定義,而後在須要的地方調用...須要咱們在實際使用過程,靈活運用這些標籤來減輕SQL的代碼量和下降複雜度。

6. resultMap標籤

resultMap標籤用於表示數據庫查詢結果和實體對象的映射關係,它是映射文件中中所複雜的一個標籤,經常使用的屬性有兩個:

<resultMap 
  #定義這個resultMap的惟一標識
  id="XXXResult"
  #返回值的全限定類名,或類型別名 
  type="com.xxx.entity.User"> 
  
     #子節點....

  </resultMap>

而它的子節點則就很是多了:

<resultMap id="XXXResult" type="java.util.HashMap"> 
    #constructor:類在實例化時,用來注入結果到構造方法中
    <constructor>
      #idArg:ID參數;標記結果做爲ID能夠幫助提升總體效能
      <idArg/>
      #arg:注入到構造方法的一個普通結果
      <arg/>
    </constructor>
    #一個 ID 結果;標記出做爲 ID 的結果能夠幫助提升總體性能        
    <id/>
    #注入到字段或 JavaBean 屬性的普通結果
    <result/>
    #一個複雜類型的關聯;許多結果將包裝成這種類型
    <association property=""/>
    #一個複雜類型的集合
    <collection property=""/>
    # 使用結果值來決定使用哪一個 resultMap
    <discriminator javaType="">
       #基於某些值的結果映射
       <case value=""></case>
    </discriminator>!
  </resultMap>

如查詢要把查詢結果的字段用駝峯的寫法映射,能夠定義一個resultMap,吧對象和實體屬性一一對應起來:

<resultMap id="UserResultMap" type="java.util.HashMap">
        <id column="id" property="id"/>
        <result column="nick_name" property="nickName"/>
        <result column="gmt_created" property="gmtCreated"/>
        <result column="gmt_modified" property="gmtModified"/>
    </resultMap>

在SQL用就能夠直接使用這個resultMap做爲返回類型:

<select id="selectUserByName" resultMap="UserResultMap">
    select id,nick_name,gmt_created,gmt_modified from user where name =#{name}
</select>

上面的例子只用到resultMap中最經常使用的兩個子標籤: <id>、<result>。還有不少其它的標籤能夠寫成高級的resultMap,因爲篇幅較長,而文章旨在入門,所以在此暫不對每一個標籤舉例子解釋,有興趣的能夠自行百度。

6. 運行原理和實操一波

看完一波語法以後,腦子處於似懂非懂的狀態,好像都是在講配置文件和mapper的使用。當咱們學會了編寫這些mapper以後,究竟應該怎麼使用它?
到這裏咱們就不得不提一下mybatis的運行過程了,先了解幾個mybatis提供的接口/類:

  1. SqlSessionFactoryBuilder : SqlSessionFactory的構造器,用於建立SqlSessionFactory,採用了Builder設計模式。
  2. SqlSessionFactory:SqlSession工廠類,以工廠形式建立SqlSession對象,採用了Factory工廠設計模式。
  3. SqlSession:執行SQL的接口

因爲mybatis的運行原理很是複雜,遠遠不是30分鐘能掌握的,所以在此只是歸納爲最大的四個過程:

  1. 加載配置建立SqlSessionFacotry
  2. 經過sqlSessionFactory獲取SqlSession
  3. SqlSession查找和轉化Mapper
  4. SqlSession執行mapper中的SQL語句

知道了運行流程以後,咱們就能夠實操一波了,雖然主流的開發框架都已經看不見這些東西了,但做者仍是決定拋棄一切框架,只用maven構建一個空白項目進行實操:

  1. 在idea上建立一個maven項目,而且在pom中引入mybatis和mysql依賴

這個簡單,很少描述。
其中pom中的依賴爲:

<dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.7</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>6.0.6</version>
        </dependency>
    </dependencies>
  1. 在resources中建立一個名爲mybatis-config.xml的配置文件,內容爲:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--properties用於定義一些屬性變量,以便在配置文件中調用-->
    <properties>
        <!--定義一個變量爲driver的屬性,在下面就能夠用${driver}來得到其屬性值-->
        <property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://10.9.0.111/test"></property>
    </properties>
    <!--定義不一樣環境下的配置,便於區分生產、測試等環節的配置-->
    <environments default="development">
       <!--定義一個環境下的配置-->
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="root"/>
                <property name="password" value="test100"/>
            </dataSource>
        </environment>
    </environments>
    <!--用於設置mapper文件的引入-->
    <mappers>
        <!--resource方式引入mapper文件-->
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>
  1. 建立表結構:
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `gmt_created` varchar(255) DEFAULT NULL,
  `gmt_modified` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
-- 插入一條數
INSERT INTO `user` VALUES ('1', 'hello mybatis', null, null);
  1. 在java下建立User.java的實體類(注意:爲了簡化代碼,getter和serter已經去掉,實操時自行補上):
public class User {
    private Integer id;
    private String name;
    private String gmtCreated;
    private String gmtModified;
   //getter 和 setter...
}
  1. 在java下建立UserMapper.java的映射類:
public interface UserMapper {
    User getUserByName(@Param("name") String name);
}
  1. 在resources下建立mapper文件夾,在mapper下建立UserMapper的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="UserMapper">
    <select id="getUserByName" resultType="User">
        select  * from  user where  name =#{name}
    </select>
</mapper>
  1. 啓動mybatis執行SQL

根據上面的運行流程,就能夠編寫一個測試類:

public static  void main(String args[]){
        try {
            String resource = "mybatis-config.xml";
//           1. 獲取配置文件的輸入流
            InputStream inputStream = Resources.getResourceAsStream(resource);
//            2. 讀取配置文件並用SqlSessionFactoryBuilder建立一個SqlSessionFactory
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//            3. 從SqlSessionFactory中獲取一個SqlSession
             SqlSession s=  sqlSessionFactory.openSession();
//             4. 查找映射SQL文件
             UserMapper mapper=s.getMapper(UserMapper.class);
//             5.執行CURD操做
            User user=mapper.getUserByName("hello mybatis");

            if(user!=null){
                System.out.print("查詢成功,個人名次是:"+user.getName());
            }

        }catch (Exception e){
            e.printStackTrace();
        }
    }

查看輸出:

查詢成功,個人名次是:hello mybatis

大功告成!有興趣的讀者能夠根據上面的過程,編寫屬於本身的原生態mybatis的測試項目,若是有問題或者須要源碼請關注公衆號留言或加微信:sisi-ceo,咱們一塊兒來征服寫代碼這作大山~


以爲本文對你有幫助?請分享給更多人
關注「編程無界」,提高裝逼技能

相關文章
相關標籤/搜索