MyBatis-基礎

定義

        MyBatis屬於數據庫相關的一個Java持久層框架,用於簡化JDBC操作。  它支持定製化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可以使用簡單的 XML 或註解來配置和映射原生信息, 只需要編寫對應的接口類而不需要寫實現類,就能夠完成對數據庫的CRUD操作。

        每個MyBatis應用程序主要都是使用SqlSessionFactory實例的,一個SqlSessionFactory實例可以通過SqlSessionFactoryBuilder獲得。SqlSessionFactoryBuilder可以從一個xml配置文件或者一個預定義的配置類的實例獲得。

優點

把sql語句提出到xml文件中,不再有Dao文件。

降低了java代碼和sql語句的耦合度

MyBatis的基本配置

     MyBatis的基本配置流程如下:

1.導入JAR包

       使用MyBatis需要導入MyBatis和數據庫驅動jar包,如下所示:

<!-- MyBatis jar包 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>
<!-- mysql驅動jar包 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.48</version>
</dependency>

2.編寫接口類

      只需要編寫對應的接口類而不需要寫實現類,就能夠完成對數據庫的CRUD操作。

3.編寫接口類對應的Mapper映射器

        一個接口類對應一個Mapper的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">
 <!-- namespace: 命名空間 (內容爲接口類的全名)每一個Mapper.java會有一個對應的Mapper.xml文件
 -->
<mapper namespace="xxx.xxxMapper">
    //...

</mapper>

4.編寫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>
    <!-- 用於控制檯輸出日誌內容 -->
    <!-- <settings>
    <setting name="logImpl" value="STDOUT_LOGGING"></setting>
    </settings> -->
    <!-- environments標籤內部可以配置多個environment,通過default選擇出需要加載的一個數據庫環境 -->
    <environments default="development">
        <!-- id值爲development的開發環境 -->
        <environment id="development">
            <!-- 事務管理,使用JDBC管理 -->
            <transactionManager type="JDBC"/>
            <!-- 數據源,使用數據庫連接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mydb3?useUnicode=true;
                                                        characterEncoding=utf-8;useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
        <!-- 後面還可以配置多個environment -->
        <environment id="xxx">
            ...
        </environment>
    </environments>
  	
    <!-- 配置Mapper映射器的路徑 -->
    <mappers>
        <mapper resource="mapper/xml/TClassMapper.xml"></mapper>
        <!-- 如果有多個mapper,則在後面繼續添加對應的mapper -->
    </mappers>
</configuration>

配置詳解如下:

 

mappers(引入映射器)

     常用的引入映射器方法有3種,如下所示:

  • 1.使用文件路徑引入映射器
<mappers>
    <mapper resource="mapper/xml/TClassMapper.xml"></mapper>
</mappers>
  • 2.使用包名引入映射器
<mappers>
    <package resource="mapper.xml"></package >
</mappers>
  • 3.使用類註冊引入映射器
<mappers>
    <class resource="mapper.xml.TClassMapper"></class >
</mappers>

 

MyBatis的組成

       MyBatis的組成如下所示:

        詳解如下:

1.SqlSessionFactoryBuilder(構造器)

      根據配置信息或代碼生成SqlSessionFactory接口。

2.SqlSessionFactory(工廠接口)

      MyBatis的應用都是以SqlSessionFactory的實例爲中心,用來生成SqlSession

3.SqlSession(Sql處理器)

       SQLSession是一個接口類,類似於JDBC的Connection對象,有如下兩種執行方法返回執行結果:

  • 獲取Mapper接口類映射器

         讓Mapper映射器通過命名空間和方法名稱去找到對應的SQL,發送到數據庫並執行,返回結果。

  • 直接執行SQL語句

   

    SqlSession支持事務,可以通過commit()和rollback()方法來提交或者回滾事務。      

4.Sql Mapper(映射規則及SQL定義)

        Sql Mapper即Mapper映射器,MyBatis的新設計組件,由Java接口和XML文件(或註解)構成,需要給出對應的SQL和映射規則。負責發送SQL去執行。並返回結果。

 

Mapper映射器配置

1.元素

       <mapper>裏面有如下元素:

select

映射查詢語句

最常用最複雜的元素。可以自定義參數,返回結果集等

update

映射更新語句

執行後返回一個整數,代表更新的條數。

delete

映射刪除語句

執行後返回一個整數,代表刪除的條數。

insert

映射插入語句

執行後返回一個整數,代表插入的條數。

sql 允許定義一部分的sql,然後可以在各個地方引用它
resultMap 用來描述從數據庫中查詢出來的結果集中來加載對象
cache 給命名空間緩存配置
cache-ref 其他命名空間緩存配置引用

2.元素的屬性

id 唯一標識符,需要和Mapper接口類中對應的方法名一樣
parameterType 傳入參數類型
resultType

返回結果類型

如果返回結果是一個數字,則可以不用寫

如果返回結果是一個實體類,則resultType="實體類名"

如果返回結果是一個List<T>集合,則resultType="T"

如果返回結果是一個Map集合,則resultType="map"

resultMap 外部resultMap的命名引用
timeout 這個設置是在拋出異常之前,驅動程序等待數據庫返回請求結果的秒數。
fetchSize 影響驅動程序每次批量返回的結果行數。

 

 

Mapper的實現原理

MapperProxyFactory中,使用JDK的動態代理生成Mapper接口的代理代理類由動態處理器MapperProxy中調用MapperMethod中的方法處理執行SQL,最後,在MapperMethod中根據執行的方法返回值決定調用SqlSession中的對應方法執行SQL

動態SQL語句

Sql標籤

       有如下標籤:

if

表示判斷是否需要添加某個條件,用於SQL語句的拼接

使用if標籤的時候,需要使用“where 1=1”, 做sql語句的拼接。避免出現sql語法錯誤(因爲缺少where關鍵字)

where

用於拼接select和delete語句

set

用於拼接update語句

trim

用於替代set和where標籤,可以拼接select、delete、update語句

  • if標籤
<select id="getEmps" parameterType="entity.Emp" resultType="entity.Emp">
    select * from emp where 1=1
    <if test="empName!=null">and empName=#{empName}</if>
    <if test="empAge!=0">and empAge > #{empAge}</if>
</select>
  • where標籤
<select id="getEmpsByWhere" parameterType="entity.Emp" resultType="entity.Emp">
    select * from emp
    <!-- 如果if條件中,有爲true的條件,那麼會添加一個where關鍵字,同時會去掉where後面的第一個and關鍵字 -->
    <where>
        <if test="empName!=null">and empName=#{empName}</if>
        <if test="empAge!=0">and empAge > #{empAge}</if>
    </where>
</select>
  • set標籤
<update id="updateEmpSet" parameterType="entity.Emp">
    update emp
    <!-- set標籤 
        set中的if標籤,條件爲真的情況,就會拼在sql語句中, 將最後的“,”去掉。
        set中的if標籤, 條件都爲假的情況,就會出現sql語法錯誤。
    -->
    <set>
        <if test="empName!=null">empName=#{empName},</if>
        <if test="empAge!=0">empAge=#{empAge},</if>
        <if test="empJob!=null">empJob=#{empJob},</if>
        <if test="deptNo!=0">deptNo=#{deptNo}</if>
    </set>
    <where>
        <if test="empNo!=0">and empNo=#{empNo}</if>
    </where>
</update>
  • trim標籤
<!-- trim的使用:替代set和where標籤, 通過屬性的設置,保證sql語句的語法正確 )
    prefix : 添加前綴 
    prefixOverrides: 刪除前面的某個內容 
    suffix:  添加後綴 
    suffixOverrides: 刪除後面的某個內容
-->
<!-- 替代where -->
<select id="getEmpsTrim" parameterType="entity.Emp" resultType="entity.Emp">
    select * from emp
    <trim prefix="where" prefixOverrides="and">
        <if test="empName!=null">and empName=#{empName}</if>
        <if test="empAge!=0">and empAge>#{empAge}</if>
        <if test="empJob!=null">and empJob like #{empJob}</if>
    </trim>
</select>
<!-- 替代set -->
<select id="updateEmpSet" parameterType="entity.Emp">
    update emp
    <trim prefix="set" suffixOverrides="," suffix=" where empNo=#{empNo}">
        <if test="empName!=null">empName=#{empName},</if>
        <if test="empAge!=0">empAge=#{empAge},</if>
        <if test="empJob!=null">empJob=#{empJob},</if>
        <if test="deptNo!=0">deptNo=#{deptNp}</if>
    </trim>
</select>

 

分頁查詢

    

select * from tableName limit begin, maxRow;
begin:查詢數據的起點
maxRow:表示查詢多少的數據(每頁的數量)
分頁:
每頁顯示的行數:maxRow
當前是第幾頁:page
計算出begin: begin
           (page-1)*maxRow
計算總頁數:pages
          rows/maxRow + 1
計算總行數:rows
          select count(*) from tableName

導入分頁查詢插件jar包

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.10</version>
</dependency>

在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> 
     <!-- 分頁插件的配置 -->
     <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!-- 
              value:表示傳入參數(page,rows)不合理時的處理方式
                爲true時:若page表示的頁面不存在時,如page<1,那麼page設爲1;如果page>最後一頁,那麼page設置爲最後一頁
                爲false時:若page表示的頁面不存在時,查詢內容爲空
            -->
            <property name="reasonable" value="true"></property>
        </plugin>
     </plugins>
    ....
	 
  </configuration>

使用相關類進行分頁

public class TestStudent {
    @Test
    public void getStudents() throws IOException {
        SqlSession sqlSession = getSqlSession();
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        //調用PageHelper的靜態方法設置要分頁的頁碼和每頁顯示的數量(需要先設置分頁的參數,然後才能再查詢數據庫)
        PageHelper.startPage(5, 5);
        List<Student> students = studentMapper.getStudents();
        //PageInfo:存放分頁相關數據,創建對象的時候,需要一個查詢的結果List作爲參數,
        //          需要設置泛型,泛型就是當前查詢的實體類
        PageInfo<Student> pageInfo = new PageInfo<>(students);
        System.out.println("總記錄數: " + pageInfo.getTotal());
        System.out.println("總頁數: " + pageInfo.getPages());
        System.out.println("每頁的數量: " + pageInfo.getPageSize());
        System.out.println("當前頁: " + pageInfo.getPageNum());
        for (Student student : students) {
            System.out.println(student);
        }
    }
	
    public SqlSession getSqlSession() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        return sessionFactory.openSession();
    }
}

 

使用MyBatis Generator插件

1.說明

      使用MyBatis Generator插件可以自動生成數據庫對應的表的實體類,mapper映射器類和mapper.xml文件。

2.導入MyBatis Generator插件

      點擊STS的Help選項,然後點擊其中的Eclipse Marketplace。然後在搜索框裏面搜索mybatis generator,然後點擊下載安裝MyBatis Generator插件。如下圖所示:

3.使用

       在資源文件夾裏面右鍵,點擊new選擇生成MyBatis Generator Configuration File。如下圖所示:

      生成的文件如下所示:

<?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="context1">
        <jdbcConnection connectionURL="???" driverClass="???" password="???" userId="???" />
        <javaModelGenerator targetPackage="???" targetProject="???" />
        <sqlMapGenerator targetPackage="???" targetProject="???" />
        <javaClientGenerator targetPackage="???" targetProject="???" type="XMLMAPPER" />
        <table schema="???" tableName="???">
            <columnOverride column="???" property="???" />
        </table>
    </context>
</generatorConfiguration>

       然後根據所選的數據庫表進行配置,配置好的如下所示:

<?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="context1">
        <!-- 數據庫連接 -->
        <jdbcConnection connectionURL="jdbc:mysql://localhost:3306/crm?useUnicode=true&amp;
                                        characterEncoding=utf-8&amp;useSSL=false" 
    	            driverClass="com.mysql.jdbc.Driver" password="root" userId="root" />
        <!-- Java實體類所在包名稱和項目名稱 -->
        <javaModelGenerator targetPackage="com.luckylas.crm.entity" targetProject="crm/src/main/java" />
        <!-- mapper.xml所在的包(targetPackage)和所在的項目(targetProject) -->
        <sqlMapGenerator targetPackage="com.luckylas.crm.mapper.xml" targetProject="crm/src/main/java" />
        <!-- mapper所在的包(targetPackage)和所在的項目(targetProject) -->
        <javaClientGenerator targetPackage="com.luckylas.crm.mapper" 
                               targetProject="crm/src/main/java" type="XMLMAPPER" />
        <!-- tableName標籤表示數據庫中的表,可以有多個,
         schema:用於指定實體類的名字,不指定則默認是表名的首字母大寫
        -->
        <table schema="User" tableName="user">
            <!-- columnOverride表示將數據庫表中字段名,在實體類中取一個新的名字。如果不指定,則會默認值-->
            <!-- <columnOverride column="UId" property="u_id" /> -->
        </table>
    </context>
</generatorConfiguration>

 

一個簡單的MyBatis實例

創建數據庫實體類,和數據庫字段一一對應

/**
 * 班級實體類
 * @author luckyliuqs
 */
public class TClass {
    private int cid;   //班級ID
    private String cname;  //班級名稱
	
    public TClass() {}
	public TClass(int cid, String cname) {
        super();
        this.cid = cid;
        this.cname = cname;
    }
    public int getCid() { return cid;}
    public void setCid(int cid) {this.cid = cid;}
    public String getCname() {return cname;}
    public void setCname(String cname) {this.cname = cname;}
    @Override
    public String toString() {
        return "TClass [cid=" + cid + ", cname=" + cname + "]";
    }	
}

編寫數據庫接口Mapper類

public interface TClassMapper {
    public List<TClass> getAll();       //獲取所有班級信息
    public int insert(TClass tClass);  //插入指定班級信息
    public void delete(int cid);        //刪除指定班級信息
    public void update(TClass tClass);  //更新指定班級信息
}

編寫接口類對應的Mapper文件

     如下所示:TClassMapper.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">
 <!-- namespace: 命名空間 (內容爲接口Mapper類的全名),每一個Mapper.java會有一個對應的Mapper.xml件 -->
<mapper namespace="mapper.TClassMapper">
    <!-- id對應爲接口Mapper類中的方法名 -->
    <!-- resultType表示返回結果的類型,這裏寫入TClass即可,如果返回結果是一個TClass則會返回這個TClass;
         如果返回的是多個TClass的集合,則會自動封裝爲List<TClass>返回 -->
    <select id="getAll" resultType="entity.TClass">
          select * from t_class;
    </select>
    
    <!-- #{s_name}, 這是從方法的參數對象中,取到參數對象中的屬性名,得到其屬性值 -->
    <insert id="insert" parameterType="tclassMap">
          insert into t_class (c_name) values (#{c_name});
    </insert>
    
    <delete id="delete">
          delete from t_class where c_id=#{c_id};
    </delete >
    
    <update id="update" parameterType="tclassMap">
          update t_class set c_name=#{cname} where c_id=#{c_id};
    </update >
</mapper>

編寫JUnit測試類

/**
 * 測試類
 */
public class TestTClass {

    @Test
    public void test() {
        try {
            // mybatis的配置文件路徑
            String resource = "mybatis-config.xml";
            // 獲取到InputStream流,初始化MyBatis配置環境
            InputStream input = Resources.getResourceAsStream(resource);
            // 得到SqlSessionFactory
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(input);
            // 得到session,打開和數據庫之間的會話
            SqlSession session = sessionFactory.openSession();
            // 得到接口
            TClassMapper clsMapper = session.getMapper(TClassMapper.class);
            //獲取到所有班級信息
            List<TClass> list = clsMapper.getAll();
            for(TClass cl : list) {
                System.out.println(cl);
            }
            //插入指定班級信息
            TClass tClass = new TClass(0,"美工");
            clsMapper.insert(tClass);
            //刪除指定班級信息
            clsMapper.delete(8);
            //更新指定班級信息
            clsMapper.update(tClass);
            //提交
            session.commit();
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

          上述使用MyBatis流程如下:

1.獲取MyBatis配置文件
2.獲取配置文件的輸入流InputStream
3.通過輸出流構建工廠SqlSessionFactory
4.通過SqlSessionFactory的openSession()方法獲得SqlSession對象
5.通過SqlSession獲取到對應實體類的Mapper接口類實例
6.通過此接口類執行對應方法

 

MyBatis與Hibernate的區別

     兩者都是持久層框架,區別如下:

Hibernate

是一個標準的ORM框架,比較重量級,學習成本高。

優點:高度封裝,使用起來不用寫SQL語句,開發週期短

缺點:SQL語句無法優化

應用場景:在於用量不大,併發量小的場景

MyBatis

不是一個ORM框架,只是對JDBC的輕量級封裝。

優點:學習成本低,SQL語句可以優化,執行效率高,速度快

缺點:編碼量大,開發週期長

應用場景:用戶量大,高併發

 

 

 

 

 

 

參考:https://www.jianshu.com/p/24302ca0e099

 

 

 

 

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