1. 程式人生 > >Mybatis01-MyBatis快速入門

Mybatis01-MyBatis快速入門

一、MyBatis

MyBatis 本是apache的一個開源專案iBatis, 2010年這個專案由apache software foundation 遷移到了google code,並且改名為MyBatis 。2013年11月遷移到Github。

iBATIS一詞來源於“internet”和“abatis”的組合,是一個基於Java的持久層框架。iBATIS提供的持久層框架包括SQL Maps和Data Access Objects(DAOs)

MyBatis 是一款優秀的持久層框架,它支援定製化 SQL、儲存過程以及高階對映。MyBatis 避免了幾乎所有的 JDBC 程式碼和手動設定引數以及獲取結果集。MyBatis 可以使用簡單的 XML 或註解來配置和對映原生資訊,將介面和 Java 的 POJOs(Plain Old Java Objects,普通的 Java物件)對映成資料庫中的記錄。

1.1、 MyBatis 的特點

簡單易學:本身就很小且簡單。沒有任何第三方依賴,最簡單安裝只有兩個jar檔案+配置幾個sql對映檔案易於學習,易於使用,通過文件和原始碼,可以比較完全的掌握它的設計思路和實現。

靈活:mybatis不會對應用程式或者資料庫的現有設計加強任何影響。sql寫在xml裡,便於統一管理和優化。通過sql基本上可以實現我們不使用資料訪問框架可以實現的所有功能,或許更多。

解除sql與程式程式碼的耦合:通過提供DAO層,將業務邏輯和資料訪問邏輯分離,使系統的設計更清晰,更易維護,更易單元測試。sql和程式碼的分離,提高了可維護性。

提供對映標籤,支援物件與資料庫的ORM欄位關係對映

提供物件關係對映標籤,支援物件關係組建維護

提供XML標籤,支援編寫動態sql。

1.2、MyBatis工作流程

(1)、載入配置並初始化

觸發條件:載入配置檔案

配置來源於兩個地方,一處是配置檔案,一處是Java程式碼的註解,將SQL的配置資訊載入成為一個個MappedStatement物件(包括了傳入引數對映配置、執行的SQL語句、結果對映配置),儲存在記憶體中。

(2)、接收呼叫請求

觸發條件:呼叫Mybatis提供的API

傳入引數:為SQL的ID和傳入引數物件

處理過程:將請求傳遞給下層的請求處理層進行處理。

(3)、處理操作請求 觸發條件:API介面層傳遞請求過來

傳入引數:為SQL的ID和傳入引數物件

處理過程:
  (A)根據SQL的ID查詢對應的MappedStatement物件。

  (B)根據傳入引數物件解析MappedStatement物件,得到最終要執行的SQL和執行傳入引數。

  (C)獲取資料庫連線,根據得到的最終SQL語句和執行傳入引數到資料庫執行,並得到執行結果。

  (D)根據MappedStatement物件中的結果對映配置對得到的執行結果進行轉換處理,並得到最終的處理結果。

  (E)釋放連線資源。

(4)、返回處理結果將最終的處理結果返回。

無論是用過的hibernate,mybatis,你都可以法相他們有一個共同點:

在java物件和資料庫之間有做mapping的配置檔案,也通常是xml 檔案

從配置檔案(通常是XML配置檔案中)得到 SessionFactory

由SessionFactory 產生 Session

在Session中完成對資料的增刪改查和事務提交等

在用完之後關閉Session

1.3、MyBatis架構

Mybatis的功能架構分為三層:

API介面層:提供給外部使用的介面API,開發人員通過這些本地API來操縱資料庫。介面層一接收到呼叫請求就會呼叫資料處理層來完成具體的資料處理。

資料處理層:負責具體的SQL查詢、SQL解析、SQL執行和執行結果對映處理等。它主要的目的是根據呼叫的請求完成一次資料庫操作。

基礎支撐層:負責最基礎的功能支撐,包括連線管理、事務管理、配置載入和快取處理,這些都是共用的東西,將他們抽取出來作為最基礎的元件。為上層的資料處理層提供最基礎的支撐。

1.4、MyBatis的主要成員如層次結構

主要成員:

Configuration:MyBatis所有的配置資訊都儲存在Configuration物件之中,配置檔案中的大部分配置都會儲存到該類中

SqlSession:作為MyBatis工作的主要頂層API,表示和資料庫互動時的會話,完成必要資料庫增刪改查功能

Executor:MyBatis執行器,是MyBatis 排程的核心,負責SQL語句的生成和查詢快取的維護

StatementHandler:封裝了JDBC Statement操作,負責對JDBC statement 的操作,如設定引數等

ParameterHandler:負責對使用者傳遞的引數轉換成JDBC Statement 所對應的資料型別

ResultSetHandler:負責將JDBC返回的ResultSet結果集物件轉換成List型別的集合

TypeHandler:負責java資料型別和jdbc資料型別(也可以說是資料表列型別)之間的對映和轉換

MappedStatement:MappedStatement維護一條<select|update|delete|insert>節點的封裝

SqlSource:負責根據使用者傳遞的parameterObject,動態地生成SQL語句,將資訊封裝到BoundSql物件中,並返回

BoundSql:表示動態生成的SQL語句以及相應的引數資訊

層次結構:

1.5、學習資源

mybatis3中文幫助:http://www.mybatis.org/mybatis-3/zh/index.html

mybatis-spring:http://www.mybatis.org/spring/zh/index.html

MyBatis中國分站:http://www.mybatis.cn/

原始碼:https://github.com/mybatis/mybatis-3/

二、MyBatis 快速入門示例

2.1、在IDEA中建立專案

普通java專案或者是Maven專案都可以,如下圖所示:

2.2、新增依賴

下載地址:https://github.com/mybatis/mybatis-3/releases

MyBatis

         mybatis-3.4.6.jar

【MYSQL驅動包】
    mysql-connector-java-5.1.38-bin.jar

   

Maven POM

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.hmy.mybatis02</groupId>
    <artifactId>Mybatis02</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!--MyBatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
        <!--MySql資料庫驅動 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <!-- JUnit單元測試工具 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>

    </dependencies>

</project>

3、建立資料庫和表,針對MySQL資料庫

CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) NOT NULL,
  `sex` enum('boy','girl','secret') DEFAULT 'secret',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

將SQL指令碼在MySQL資料庫中執行,完成建立資料庫和表的操作,如下:

  

表中的資料如下:

2.3、新增Mybatis配置檔案

在Resources目錄下建立一個conf.xml檔案,如下圖所示:

conf.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>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/studentMapper.xml"/>
    </mappers>
</configuration>

解釋

2.4、定義表所對應的實體類

Student實體類的程式碼如下:

package com.hanlu.mybatis02.entities;


public class Student {

  private int id;
  private String name;
  private String sex;


  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }


  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }


  public String getSex() {
    return sex;
  }

  public void setSex(String sex) {
    this.sex = sex;
  }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }
}

2.5、定義操作Student表的sql對映檔案

在resources目錄下建立一個mapper目錄,專門用於存放sql對映檔案,在目錄中建立一個studentMapper.xml檔案,如下圖所示:

studentMapper.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,namespace的值習慣上設定成包名+sql對映檔名,這樣就能夠保證namespace的值是唯一的
例如namespace="com.hanlu.mybatis02.dao.studentMapper"就是com.hanlu.mybatis02.dao(包名)+studentMapper(studentMapper.xml檔案去除字尾)
-->
<mapper namespace="com.hanlu.mybatis02.dao.studentMapper">
    <!-- 在select標籤中編寫查詢的SQL語句, 設定select標籤的id屬性為selectStudentById,id屬性值必須是唯一的,不能夠重複
 使用parameterType屬性指明查詢時使用的引數型別,resultType屬性指明查詢返回的結果集型別
resultType="com.hanlu.mybatis02.entities.Student"就表示將查詢結果封裝成一個Student類的物件返回
Student類就是student表所對應的實體類
-->
    <!-- 
    根據id查詢得到一個user物件
 -->
    <select id="selectStudentById" resultType="com.hanlu.mybatis02.entities.Student">
        select * from student where id = #{id}
    </select>
</mapper>

解釋

參考:https://www.cnblogs.com/hellokitty1/p/5216025.html

2.6、在配置檔案中註冊對映檔案

在配置檔案conf.xml中註冊studentMapper.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>
    <environments default="development">
        <environment id="development">
            <!-- 配置資料庫連線資訊 -->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!-- 註冊studentMapper.xml檔案studentMapper.xml位於mapper這個目錄下,所以resource寫成mapper/studentMapper.xml-->
        <mapper resource="mapper/studentMapper.xml"/>
    </mappers>
</configuration>

2.7、編寫資料訪問類

StudentDao.java,執行定義的select語句

package com.hanlu.mybatis02.dao;

import com.hanlu.mybatis02.entities.Student;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;

public class StudentDao {

    public Student getStudentById(int id){
        //使用類載入器載入mybatis的配置檔案(它也載入關聯的對映檔案)
        InputStream stream=StudentDao.class.getClassLoader().getResourceAsStream("conf.xml");
        //構建sqlSession的工廠
        SqlSessionFactory ssf=new SqlSessionFactoryBuilder().build(stream);
        //使用MyBatis提供的Resources類載入mybatis的配置檔案(它也載入關聯的對映檔案)
        //Reader reader = Resources.getResourceAsReader(resource);
        //構建sqlSession的工廠
        //SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
        
        //建立能執行對映檔案中sql的sqlSession
        SqlSession session=ssf.openSession();
        /**
         * 對映sql的標識字串,
         * com.hanlu.mybatis02.dao.studentMapper是studentMapper.xml檔案中mapper標籤的namespace屬性的值,
         * selectStudentById是select標籤的id屬性值,通過select標籤的id屬性值就可以找到要執行的SQL
         */
        Student student=session.selectOne("com.hanlu.mybatis02.dao.studentMapper.selectStudentById",1);
        return student;
    }

    public static void main(String[] args) {
        StudentDao dao=new StudentDao();
        Student student=dao.getStudentById(1);
        System.out.println(student);
    }
}

執行過程解釋:

 

1、mybatis配置

SqlMapConfig.xml,此檔案作為mybatis的全域性配置檔案,配置了mybatis的執行環境等資訊。

mapper.xml檔案即sql對映檔案,檔案中配置了操作資料庫的sql語句。此檔案需要在SqlMapConfig.xml中載入。

2、通過mybatis環境等配置資訊構造SqlSessionFactory即會話工廠

3、由會話工廠建立sqlSession即會話,操作資料庫需要通過sqlSession進行。

4、mybatis底層自定義了Executor執行器介面操作資料庫,Executor介面有兩個實現,一個是基本執行器、一個是快取執行器。

5、Mapped Statement也是mybatis一個底層封裝物件,它包裝了mybatis配置資訊及sql對映資訊等。mapper.xml檔案中一個sql對應一個Mapped Statement物件,sql的id即是Mapped statement的id。

6、Mapped Statement對sql執行輸入引數進行定義,包括HashMap、基本型別、pojo,Executor通過Mapped Statement在執行sql前將輸入的java物件對映至sql中,輸入引數對映就是jdbc程式設計中對preparedStatement設定引數。

7、Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本型別、pojo,Executor通過Mapped Statement在執行sql後將輸出結果對映至java物件中,輸出結果對映過程相當於jdbc程式設計中對結果的解析處理過程。

參考:https://www.cnblogs.com/selene/p/4604605.html

2.8、編寫單元測試

import com.hanlu.mybatis02.dao.StudentDao;
import com.hanlu.mybatis02.entities.Student;
import org.junit.Test;
import org.junit.Before;
import org.junit.After;


public class StudentDaoTest {

    @Before
    public void before() throws Exception {
    }

    @After
    public void after() throws Exception {
    }

    /**
     * Method: getStudentById(int id)
     */
    @Test
    public void testGetStudentById() throws Exception {
        StudentDao dao=new StudentDao();
        Student student=dao.getStudentById(1);
        System.out.println(student);
    }


}

測試結果:

2.9、IDEA中Junit外掛與生成測試類位置

開啟IntelliJ IDEA工具,Alt+Ctrl+S,開啟設定視窗,點選進入Plugins。

從外掛資源庫中搜索JunitGenerator V2.0版本

安裝此外掛,重啟IDEA就可以了。

現在可通過此工具自動完成test類的生成了,在需要進行單元測試的類中按 Alt+Insert

選中你要建立測試用例的方法即可。

IntelliJ IDEA JUnit Generator自動建立測試用例到指定test目錄

1.開啟File->Settings

2.搜尋junit,找到JUnit Generator

3.Properties選項卡里的Output Path為測試用例生成的目錄,修改為test目錄:

SOURCEPATH/../../test/java/SOURCEPATH/../../test/java/{PACKAGE}/${FILENAME}

4.切換到JUnit 4選項卡,可以修改生成測試用例的模板,比如類名、包名等

修改生成位置:

修改模板檔案:

測試類生成目錄分析:

${SOURCEPATH}/test/${PACKAGE}/${FILENAME}
$SOURCEPATH/../../test/java/{PACKAGE}/${FILENAME}

 

對應的目錄結構為

${SOURCEPATH}是到src/main/java這一層

../是退到上一層目錄的意思,對著圖理解一下

三、基於XML對映實現完整資料訪問

MyBatis可以使用XML或註解作為對映器的描述,XML強大且可以解偶,註解方便且簡單。

因為每一個操作都需要先拿到會話,這裡先定義一個工具類以便複用:

會話工具類:

 

package com.hanlu.mybatis02.utils;

import com.hanlu.mybatis02.dao.StudentDao;
import com.hanlu.mybatis02.entities.Student;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

/**
 * @author HMY
 * @date 2018/10/17-17:07
 */

/**
 * MyBatis 會話工具類
 * */
public class SqlSessionFactoryUtil {

/**
     * 獲得會話工廠
     *
     * */
    public static SqlSessionFactory getFactory(){

        InputStream inputStream=null;
        SqlSessionFactory sqlSessionFactory=null;
        try {
            //載入conf.xml配置檔案,轉換成輸入流
            inputStream= StudentDao.class.getClassLoader().getResourceAsStream("conf.xml");
            //根據配置檔案的輸入流構造一個SQL會話工廠
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        }finally {
            if (inputStream!=null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sqlSessionFactory;
    }

    /**
     * 獲得sql會話,是否自動提交
     * */
    public static SqlSession openSession(boolean isAutoCommit){
        return getFactory().openSession(isAutoCommit);
    }
    
    /**
     * 關閉會話
     * */
    public static void closeSession(SqlSession session){
        if (session!=null){
            session.close();
        }
    }

}
            

XML對映器studentMapper:

<?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.hanlu.mybatis02.studentMapper">

    <select id="selectStudentById" resultType="student">
        select id,name,sex from student where id = #{id}
    </select>

    <select id="selectStudentByName" parameterType="String" resultType="Student">
        select id,name,sex from student where name LIKE '%${value}%'
    </select>

    <insert id="insertStudent" parameterType="student">
        insert into student(name,sex) values (#{name},#{sex})
    </insert>

    <update id="updateStudent" parameterType="student">
        UPDATE student SET name=#{name},sex=#{sex} WHERE id=#{id}
    </update>

    <delete id="deleteStudent" parameterType="int">
        DELETE FROM student WHERE id=#{id}
    </delete>
</mapper>

資料訪問類StudentDao.java:

package com.hanlu.mybatis02.dao;

import com.hanlu.mybatis02.entities.Student;
import com.hanlu.mybatis02.utils.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.InputStream;
import java.util.List;

/**
 * @author HMY
 * @date 2018/10/17-10:20
 */
public class StudentDao implements StudentMapper {

    
    public Student selectStudentById(int id) {
        Student entity = null;

        /* //載入conf.xml配置檔案,轉換成輸入流
        InputStream inputStream=StudentDao.class.getClassLoader().getResourceAsStream("conf.xml");

        //根據配置檔案的輸入流構造一個SQL會話工廠
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);

        //開啟一個會話
        SqlSession session = sqlSessionFactory.openSession();*/

        //開啟一個會話
        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //查詢單個物件
        entity = session.selectOne("com.hanlu.mybatis02.studentMapper.selectStudentById", id);

        //關閉會話
        SqlSessionFactoryUtil.closeSession(session);

        return entity;
    }

    public List<Student> selectStudentByName(String name) {
        /*InputStream inputStream=StudentDao.class.getClassLoader().getResourceAsStream("conf.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session=sqlSessionFactory.openSession();*/

        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        List<Student> list = session.selectList("com.hanlu.mybatis02.studentMapper.selectStudentByName", name);

        SqlSessionFactoryUtil.closeSession(session);

        return list;
    }

    public int insertStudent(Student student) {
        int rows = 0;
        SqlSession session = SqlSessionFactoryUtil.openSession(true);
        rows = session.insert("com.hanlu.mybatis02.studentMapper.insertStudent", student);
        SqlSessionFactoryUtil.closeSession(session);
        return rows;
    }

    public int updateStudent(Student student) {
        int rows = 0;
        SqlSession session = SqlSessionFactoryUtil.openSession(true);
        rows = session.update("com.hanlu.mybatis02.studentMapper.updateStudent", student);
        SqlSessionFactoryUtil.closeSession(session);
        return rows;
    }

    public int deleteStudent(int id) {
        int rows = 0;
        SqlSession session = SqlSessionFactoryUtil.openSession(true);
        rows = session.delete("com.hanlu.mybatis02.studentMapper.updateStudent", id);
        SqlSessionFactoryUtil.closeSession(session);
        return rows;
    }

}
    

單元測試:

package com.hanlu.mybatis02.dao; 

import com.hanlu.mybatis02.entities.Student;
import org.junit.Assert;
import org.junit.Test;
import org.junit.Before; 
import org.junit.After;

import java.util.List;

/** 
* StudentDao Tester. 
* 
* @author <Authors name> 
* @since <pre>ʮ�� 17, 2018</pre> 
* @version 1.0 
*/ 
public class StudentDaoTest { 
StudentDao dao;
@Before
public void before() throws Exception {
    dao=new StudentDao();
} 

@After
public void after() throws Exception { 
} 

/** 
* 
* Method: selectStudentById(int id) 
* 
*/ 
@Test
public void testSelectStudentById() throws Exception { 
//TODO: Test goes here... 
} 

/** 
* 
* Method: selectStudentByName(String name) 
* 
*/ 
@Test
public void testSelectStudentByName() throws Exception {

    List<Student> list=dao.selectStudentByName("i");
    System.out.println(list);
    Assert.assertNotNull(list);
} 
@Test
public void testInsertStudent() throws Exception {

    Student student=new Student();
    student.setName("瑪麗");
    student.setSex("girl");
    Assert.assertEquals(1,dao.insertStudent(student));
}

@Test
public void testUpdateStudent() throws Exception {

    Student student=dao.selectStudentById(5);
    student.setSex("boy");
    student.setName("Mario");
    Assert.assertEquals(1,dao.updateStudent(student));
}


} 

參考對映檔案1:

<?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 namespace="com.san.mapper.UserMapper">

    <!-- 通過ID查詢使用者 -->
    <select id="findUserById" parameterType="int" resultType="user">
        select * from user where id=#{id}
    </select>

    <!-- 定義sql片段 -->
    <!-- sql片段內,可以定義sql語句中的任何內容 -->
    <!-- sql片段內,最好不要使用where和select關鍵字宣告在內 -->
    <sql id="whereClause">
        <!-- if標籤:對輸入的引數進行判斷 -->
        <!-- test標籤:指定判斷的表示式 -->
        <if test="user!=null">
            <!-- 判斷使用者名稱不為空 -->
            <if test="user.username!=null and user.username!=''">
                and username like '%${user.username}%'
            </if>

            <!-- 判斷性別不為空 -->
            <if test="user.sex!=null and user.sex!=''">
                and sex=#{user.sex}
            </if>
        </if>

        <!-- 判斷集合 -->
        <!-- collection:表示pojo中集合屬性的屬性名稱 -->
        <!-- item:為遍歷出的結果宣告一個變數名稱 -->
        <!-- open:遍歷開始時,需要拼接的字串 -->
        <!-- close:遍歷結束時,需要拼接的字串 -->
        <!-- separator:遍歷中間需要拼接的字串 -->
        <if test="idList!=null">
            and id in
            <foreach collection="idList" item="id" open="(" close=")" separator=",">
                <!-- and id in (#{id},#{id},#{id}) -->
                #{id}
            </foreach>
        </if>
    </sql>

    <!-- 綜合查詢,查詢使用者列表 -->
    <!-- #{}中的引數名稱要和包裝pojo中的物件層級一致,並且屬性名稱要一致 -->
    <select id="findUserList" parameterType="com.san.model.UserQueryvo" resultType="user">
        select * from user
        <!-- where標籤:預設去掉後面第一個and,如果沒有引數,則把自己幹掉 -->
        <where> 
            <!-- 引入sql片段 -->
            <include refid="whereClause"></include>
        </where>
    </select>

    <!-- 綜合查詢,查詢使用者的總數 -->
    <select id="findUserCount" parameterType="com.san.model.UserQueryvo" resultType="int">
        select count(*) from user 
        <where>
            <include refid="whereClause"></include>
        </where>

    </select>

    <!-- id標籤:專門為查詢結果中唯一列對映 -->
    <!-- result標籤:對映查詢結果中的普通列 -->
    <!-- type標籤:返回型別 -->
    <resultMap type="user" id="UserResMap">
        <id column="id_" property="id"/>
        <result column="username_" property="username"/>
        <result column="sex_" property="sex"/>
    </resultMap>    
    <select id="findUserRstMap" parameterType="int" resultMap="UserResMap">
        select id id_,username username_,sex sex_ from user where id=#{id}  
    </select>
</mapper>
View Code

參考對映檔案2:

<?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名稱空間,作用就是對sql進行分類化的管理,理解為sql隔離
    注意:使用mapper代理開發時,namespace有特殊作用
 -->
<mapper namespace="test">
<!-- 在對映檔案中配置很多sql語句 -->
<!-- 需求:通過Id查詢使用者表的記錄 -->
<!-- 通過SELECT執行資料庫查詢 
    id:標識對映檔案中的sql,稱為statement的id;
        將sql語句封裝在mapperStatement的物件中,所以Id稱為Statement的id;
    parameterType:指定輸入引數的型別,這裡指定int型
    #{}:表示一個佔位符;
    #{id}:其中Id表示接收輸入的引數,引數名稱就是Id,如果輸入引數是簡單型別,#{}中的引數名可以任意,可以是value或者其它名稱;
    resultType:指定sql輸出結果所對映的java物件型別,select指定resultType表示將單條記錄對映成java物件。
-->
<select id="findUserById" parameterType="int" resultType="com.mybatis.entity.User" >
    select * from t_user where id=#{id}
</select>
<!-- 根據使用者名稱稱模糊查詢使用者資訊,可能返回多條資料
    resultType:指定的就是單條記錄所對映的java型別;
    ${}:表示拼接sql字串,將接收到的引數內容不加任何修飾拼接在sql中.
    使用${}拼接sql,可能會引起sql注入
    ${value}:接收輸入引數的內容,如果傳入的是簡單型別,${}中只能使用value
 -->
<select id="findUserByName" parameterType="java.lang.String" resultType="com.mybatis.entity.User" >
    select * from t_user where username LIKE '%${value}%'
</select>
<!-- 新增使用者 
parameterType:指定輸入的引數型別是pojo(包括使用者資訊);
#{}中指定pojo的屬性名稱,接收到pojo物件的屬性值    ,mybatis通過OGNL(類似struts2的OGNL)獲取物件的屬性值
-->
<insert id="insertUser" parameterType="com.mybatis.entity.User" >
    <!-- 
        將insert插入的資料的主鍵返回到User物件中;
        select last_insert_id():得到剛insert進去記錄的主鍵值,只適用於自增主鍵;
        keyProperty:將查詢到的主鍵值,設定到parameterType指定的物件的那個屬性
        order:select last_insert_id()執行順序,相對於insert語句來說它的執行順序。
        resultType:指定select last_insert_id()的結果型別;
     -->
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
        select last_insert_id()
    </selectKey>
    <!-- 
        使用mysql的uuid(),實現非自增主鍵的返回。
        執行過程:通過uuid()得到主鍵,將主鍵設定到user物件的Id的屬性中,其次,在insert執行時,從user物件中取出Id屬性值;
     <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
        select uuid()
    </selectKey>
        insert into t_user (id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address})
     -->
    insert into t_user (username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
</insert>
<!-- 刪除使用者 
    根據ID刪除使用者,需要輸入Id值
-->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from t_user where id=#{id}
    </delete>
<!-- 更新使用者 
    需要傳入使用者的Id和使用者的更新資訊
    parameterType:指定User物件,包括Id和使用者的更新資訊,注意:Id是必須存在的
    #{id}:從輸入的User物件中獲取Id的屬性值
-->
<update id="updateUser" parameterType="com.mybatis.entity.User">
    update t_user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} 
    where id=#{id}
</update>

</mapper>
View Code

四、基於註解對映實完整資料訪問

對映器,StudentMapper介面:

package com.hanlu.mybatis02.dao;

import com.hanlu.mybatis02.entities.Student;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import java.util.List;

/**
 * @author HMY
 * @date 2018/10/17-20:34
 */
public interface StudentMapper {

    /**
     * 根據學生編號獲得學生物件
     */
    @Select("select id,name,sex from student where id=#{id}")
    Student selectStudentById(int id);

    @Select("select id,name,sex from student where name LIKE '%${value}%'")
    List<Student> selectStudentByName(String name);

    @Insert("insert into student(name,sex) values (#{name},#{sex})")
    int insertStudent(Student student);

    @Update("UPDATE student SET name=#{name},sex=#{sex} WHERE id=#{id}")
    int updateStudent(Student student);

    @Delete("DELETE FROM student WHERE id=#{id}")
    int deleteStudent(int id);
}

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 resource="db.properties">
        <property name="driver" value="com.mysql.jdbc.Driver"></property>
    </properties>

    <settings>
        <setting name="cacheEnabled" value="true"/>
        <!--設定日誌輸出的目標-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <typeAliases>
        <!--
                <typeAlias type="com.hanlu.mybatis02.entities.Student" alias="student"></typeAlias>
        -->
        <package name="com.hanlu.mybatis02.entities"></package>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${mysql.driver}"/>
                <property name="url" value="${mysql.url}"/>
                <property name="username" value="${mysql.username}"/>
                <property name="password" value="${mysql.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--根據路徑註冊一個基於XML的對映器-->
        <!--<mapper resource="mapper/studentMapper.xml"/>-->
        <!--根據型別註冊一個基於註解的對映器,介面-->
        <mapper class="com.hanlu.mybatis02.dao.StudentMapper"></mapper>
        <!--根據包名批量註冊包下所有基於註解的對映器,介面-->
        <mapper class="com.hanlu.mybatis02.dao"></mapper>
    </mappers>
</configuration>

StudentDaoAnno.java實現對student的資料訪問:

package com.hanlu.mybatis02.dao;

import com.hanlu.mybatis02.entities.Student;
import com.hanlu.mybatis02.utils.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;

import java.util.List;

/**
 * @author HMY
 * @date 2018/10/17-10:20
 */
public class StudentDaoAnno implements StudentMapper {

    public Student selectStudentById(int id) {
        Student entity = null;

        /*//載入conf.xml配置檔案,轉換成輸入流
        InputStream inputStream=StudentDao.class.getClassLoader().getResourceAsStream("conf.xml");

        //根據配置檔案的輸入流構造一個SQL會話工廠
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);

        //開啟一個會話
        SqlSession session = sqlSessionFactory.openSession();*/

        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //獲得對映器
        StudentMapper mapper = session.getMapper(StudentMapper.class);

        //查詢單個物件
        entity = mapper.selectStudentById(id);

        SqlSessionFactoryUtil.closeSession(session);

        //關閉會話
        return entity;
    }

    public List<Student> selectStudentByName(String name) {
        /*InputStream inputStream=StudentDao.class.getClassLoader().getResourceAsStream("conf.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session=sqlSessionFactory.openSession();*/

        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //獲得對映器
        StudentMapper mapper = session.getMapper(StudentMapper.class);

        List<Student> list = mapper.selectStudentByName(name);

        SqlSessionFactoryUtil.closeSession(session);

        return list;
    }

    public int insertStudent(Student student) {
        int rows = 0;
        SqlSession session = SqlSessionFactoryUtil.openSession(true);
        //獲得對映器
        StudentMapper mapper = session.getMapper(StudentMapper.class);

        rows = mapper.insertStudent(student);
        SqlSessionFactoryUtil.closeSession(session);
        return rows;
    }

    public int updateStudent(Student student) {
        int rows = 0;
        SqlSession session = SqlSessionFactoryUtil.openSession(true);
        //獲得對映器
        StudentMapper mapper = session.getMapper(StudentMapper.class);

        rows = mapper.updateStudent(student);
        SqlSessionFactoryUtil.closeSession(session);
        return rows;
    }

    public int deleteStudent(int id) {
        int rows = 0;
        SqlSession session = SqlSessionFactoryUtil.openSession(true);
        //獲得對映器
        StudentMapper mapper = session.getMapper(StudentMapper.class);

        rows = mapper.deleteStudent(id);
        SqlSessionFactoryUtil.closeSession(session);
        return rows;
    }

}

單元測試:

package com.hanlu.mybatis02.dao;

import com.hanlu.mybatis02.entities.Student;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

/** 
* StudentDao Tester. 
* 
* @author <Authors name> 
* @since <pre>ʮ�� 17, 2018</pre> 
* @version 1.0 
*/ 
public class StudentDaoAnnoTest {
StudentMapper dao;

@Before
public void before() throws Exce