MyBatis學習總結(二)——MyBatis核心配置文件與輸入輸出映射

在上一章中咱們學習了《MyBatis學習總結(一)——ORM概要與MyBatis快速起步》,這一章主要是介紹MyBatis核心配置文件、使用接口+XML實現完整數據訪問、輸入參數映射與輸出結果映射等內容。html

1、MyBatis配置文件概要

MyBatis核心配置文件在初始化時會被引用,在配置文件中定義了一些參數,固然能夠徹底不須要配置文件,所有經過編碼實現,該配置文件主要是是起到解偶的做用。如第一講中咱們用到conf.xml文件:java

<?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://127.0.0.1:3306/nfmall?useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="uchr@123"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--<mapper resource="mapper/studentMapper.xml"/>-->
        <mapper class="com.zhangguo.mybatis02.dao.StudentMapper"></mapper>
    </mappers>
</configuration>

MyBatis 的配置文件包含了會深深影響 MyBatis 行爲的設置(settings)和屬性(properties)信息。文檔的頂層結構以下::mysql

  1. configuration 配置

2、MyBatis配置文件詳解

該配置文件的官方詳細描述能夠點擊這裏打開git

2.一、properties屬性

做用:將數據鏈接單獨配置在db.properties中,只須要在myBatisConfig.xml中加載db.properties的屬性值,在myBatisConfig.xml中就不須要對數據庫鏈接參數進行硬編碼。數據庫鏈接參數只配置在db.properties中,方便對參數進行統一管理,其它xml能夠引用該db.properties。sql

db.properties的內容:數據庫

##MySQL鏈接字符串
#驅動
mysql.driver=com.mysql.jdbc.Driver
#地址
mysql.url=jdbc:mysql://127.0.0.1:3306/nfmall?useUnicode=true&amp;characterEncoding=UTF-8
#用戶名
mysql.username=root
#密碼
mysql.password=uchr@123

在myBatisConfig.xml中加載db.propertiesapache

<?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>
    <!--導入db.properties文件中的全部key-value數據-->
    <properties resource="db.properties">
        <!--定義一個名稱爲driver,值爲com.mysql.jdbc.Driver的屬性-->
        <property name="driver" value="com.mysql.jdbc.Driver"></property>
    </properties>
    <!--環境配置,default爲默認選擇的環境-->
    <environments default="work">
        <!--開發-->
        <environment id="development">
            <!--事務管理-->
            <transactionManager type="JDBC"/>
            <!--鏈接池-->
            <dataSource type="POOLED">
                <!--引用屬性${mysql.driver}-->
                <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>
        <!--運行-->
        <environment id="work">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/nfmall?useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="uchr@123"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!--<mapper resource="mapper/studentMapper.xml"/>-->
        <mapper class="com.zhangguo.mybatis02.dao.StudentMapper"></mapper>
    </mappers>
</configuration>

properties特性:編程

注意:api

  • 在properties元素體內定義的屬性優先讀取。
  • 而後讀取properties元素中resource或url加載的屬性,它會覆蓋已讀取的同名屬性。
  • 最後讀取parameterType傳遞的屬性,它會覆蓋已讀取的同名屬性

建議:緩存

  不要在properties元素體內添加任何屬性值,只將屬性值定義在properties文件中。

  在properties文件中定義屬性名要有必定的特殊性,如xxxx.xxxx(jdbc.driver)

2.二、settings全局參數配置

mybatis框架運行時能夠調整一些運行參數。好比,開啓二級緩存,開啓延遲加載等等。全局參數會影響mybatis的運行行爲。

mybatis-settings的配置屬性以及描述

setting(設置) Description(描述) valid Values(驗證值組) Default(默認值)
cacheEnabled 在全局範圍內啓用或禁用緩存配置 任何映射器在此配置下。 true | false TRUE
lazyLoadingEnabled 在全局範圍內啓用或禁用延遲加載。禁用時,全部相關聯的將熱加載。 true | false TRUE
aggressiveLazyLoading 啓用時,有延遲加載屬性的對象將被徹底加載後調用懶惰的任何屬性。不然,每個屬性是按需加載。 true | false TRUE
multipleResultSetsEnabled 容許或不容許從一個單獨的語句(須要兼容的驅動程序)要返回多個結果集。 true | false TRUE
useColumnLabel 使用列標籤,而不是列名。在這方面,不一樣的驅動有不一樣的行爲。參考驅動文檔或測試兩種方法來決定你的驅動程序的行爲如何。 true | false TRUE
useGeneratedKeys 容許JDBC支持生成的密鑰。兼容的驅動程序是必需的。此設置強制生成的鍵被使用,若是設置爲true,一些驅動會不兼容性,但仍然能夠工做。 true | false FALSE
autoMappingBehavior 指定MyBatis的應如何自動映射列到字段/屬性。NONE自動映射。 PARTIAL只會自動映射結果沒有嵌套結果映射定義裏面。 FULL會自動映射的結果映射任何複雜的(包含嵌套或其餘)。

NONE,PARTIAL,FULL

PARTIAL
defaultExecutorType 配置默認執行人。SIMPLE執行人確實沒有什麼特別的。 REUSE執行器重用準備好的語句。 BATCH執行器重用語句和批處理更新。

SIMPLE,REUSE,BATCH

SIMPLE
safeRowBoundsEnabled 容許使用嵌套的語句RowBounds。 true | false FALSE
mapUnderscoreToCamelCase 從經典的數據庫列名A_COLUMN啓用自動映射到駱駝標識的經典的Java屬性名aColumn。 true | false FALSE
localCacheScope MyBatis的使用本地緩存,以防止循環引用,並加快反覆嵌套查詢。默認狀況下(SESSION)會話期間執行的全部查詢緩存。若是localCacheScope=STATMENT本地會話將被用於語句的執行,只是沒有將數據共享之間的兩個不一樣的調用相同的SqlSession。

SESSION

STATEMENT

SESSION
dbcTypeForNull 指定爲空值時,沒有特定的JDBC類型的參數的JDBC類型。有些驅動須要指定列的JDBC類型,但其餘像NULL,VARCHAR或OTHER的工做與通用值。 JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER OTHER
lazyLoadTriggerMethods 指定觸發延遲加載的對象的方法。 A method name list separated by commas equals,clone,hashCode,toString
defaultScriptingLanguage 指定所使用的語言默認爲動態SQL生成。 A type alias or fully qualified class name.

org.apache.ibatis.scripting.xmltags

.XMLDynamicLanguageDriver

callSettersOnNulls 指定若是setter方法或map的put方法時,將調用檢索到的值是null。它是有用的,當你依靠Map.keySet()或null初始化。注意(如整型,布爾等)不會被設置爲null。 true | false FALSE
logPrefix 指定的前綴字串,MyBatis將會增長記錄器的名稱。 Any String Not set
logImpl 指定MyBatis的日誌實現使用。若是此設置是不存在的記錄的實施將自動查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING Not set
proxyFactory 指定代理工具,MyBatis將會使用建立懶加載能力的對象。 CGLIB | JAVASSIST  CGLIB

官方文檔settings的例子:

<setting name="cacheEnabled" value="true"/>
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="multipleResultSetsEnabled" value="true"/>
    <setting name="useColumnLabel" value="true"/>
    <setting name="useGeneratedKeys" value="false"/>
    <setting name="autoMappingBehavior" value="PARTIAL"/>
    <setting name="defaultExecutorType" value="SIMPLE"/>
    <setting name="defaultStatementTimeout" value="25"/>
    <setting name="safeRowBoundsEnabled" value="false"/>
    <setting name="mapUnderscoreToCamelCase" value="false"/>
    <setting name="localCacheScope" value="SESSION"/>
    <setting name="jdbcTypeForNull" value="OTHER"/>
    <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
View Code

示例:

這裏設置MyBatis的日誌輸出到控制檯:

    <!--外部引入的內容將覆蓋內部定義的-->
    <properties resource="db.properties">
        <!--定義一個名稱爲driver,值爲com.mysql.jdbc.Driver的屬性-->
        <property name="mysql.driver" value="com.mysql.jdbc.Driver"></property>
    </properties>
    
    <settings>
        <!--設置是否容許緩存-->
        <setting name="cacheEnabled" value="true"/>
        <!--設置日誌輸出的目標-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

結果:

2.三、typeAiases(別名)

mapper.xml中,定義不少的statementstatement須要parameterType指定輸入參數的類型、須要resultType指定輸出結果的映射類型。

若是在指定類型時輸入類型全路徑,不方便進行開發,能夠針對parameterTyperesultType指定的類型定義一些別名,在mapper.xml中經過別名定義,方便開發。

以下所示類型com.zhangguo.mybatis02.entities.Student會反覆出現,冗餘:

 

<?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.zhangguo.mybatis02.mapper.studentMapper">
    <select id="selectStudentById" resultType="com.zhangguo.mybatis02.entities.Student">
        SELECT id,name,sex from student where id=#{id}
    </select>

    <select id="selectStudentsByName" parameterType="String" resultType="com.zhangguo.mybatis02.entities.Student">
      SELECT id,name,sex from student where name like '%${value}%';
    </select>

    <insert id="insertStudent" parameterType="com.zhangguo.mybatis02.entities.Student">
        insert into student(name,sex) VALUES(#{name},'${sex}')
    </insert>

    <update id="updateStudent" parameterType="com.zhangguo.mybatis02.entities.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>

2.3.1.MyBatis默認支持的別名

別名

映射的類型

_byte 

byte 

_long 

long 

_short 

short 

_int 

int 

_integer 

int 

_double 

double 

_float 

float 

_boolean 

boolean 

string 

String 

byte 

Byte 

long 

Long 

short 

Short 

int 

Integer 

integer 

Integer 

double 

Double 

float 

Float 

boolean 

Boolean 

date 

Date 

decimal 

BigDecimal 

bigdecimal 

BigDecimal 

2.3.2.自定義別名

(一)、單個別名定義(在myBatisConfig.xml)  

    <settings>
        <!--設置是否容許緩存-->
        <setting name="cacheEnabled" value="true"/>
        <!--設置日誌輸出的目標-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <!--別名-->
    <typeAliases>
        <!--定義單個別名,指定名稱爲student,對應的類型爲com.zhangguo.mybatis02.entities.Student-->
        <typeAlias type="com.zhangguo.mybatis02.entities.Student" alias="student"></typeAlias>
    </typeAliases>

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="com.zhangguo.mybatis02.mapper.studentMapper">
    <select id="selectStudentById" resultType="student">
        SELECT id,name,sex from student where id=#{id}
    </select>

    <select id="selectStudentsByName" 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>

(二)批量定義別名,掃描指定的包

定義單個別名的缺點很明顯,若是項目中有不少別名則須要一個一個定義,且修改類型了還要修改配置文件很是麻煩,能夠指定一個包,將下面全部的類都按照必定的規則定義成別名:

 

    <settings>
        <!--設置是否容許緩存-->
        <setting name="cacheEnabled" value="true"/>
        <!--設置日誌輸出的目標-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <!--別名-->
    <typeAliases>
        <!--定義單個別名,指定名稱爲student,對應的類型爲com.zhangguo.mybatis02.entities.Student-->
        <!--<typeAlias type="com.zhangguo.mybatis02.entities.Student" alias="student"></typeAlias>-->
        <!--指定包名下全部的類被自動掃描並定義默認別名,
        mybatis會自動掃描包中的pojo類,自動定義別名,別名就是類名(首字母大寫或小寫均可以)-->
        <package name="com.zhangguo.mybatis02.entities"></package>
    </typeAliases>

 若是com.zhangguo.mybatis02.entities包下有一個名爲Student的類,則使用別名時能夠是:student,或Student。

你必定會想到當兩個名稱相同時的衝突問題,可使用註解解決

解決方法:

2.四、typeHandlers(類型處理器)

mybatis中經過typeHandlers完成jdbc類型和java類型的轉換。

一般狀況下,mybatis提供的類型處理器知足平常須要,不須要自定義.

mybatis支持類型處理器:

類型處理器

Java類型

JDBC類型

BooleanTypeHandler 

Boolean,boolean 

任何兼容的布爾值

ByteTypeHandler 

Byte,byte 

任何兼容的數字或字節類型

ShortTypeHandler 

Short,short 

任何兼容的數字或短整型

IntegerTypeHandler 

Integer,int 

任何兼容的數字和整型

LongTypeHandler 

Long,long 

任何兼容的數字或長整型

FloatTypeHandler 

Float,float 

任何兼容的數字或單精度浮點型

DoubleTypeHandler 

Double,double 

任何兼容的數字或雙精度浮點型

BigDecimalTypeHandler 

BigDecimal 

任何兼容的數字或十進制小數類型

StringTypeHandler 

String 

CHAR和VARCHAR類型

ClobTypeHandler 

String 

CLOB和LONGVARCHAR類型

NStringTypeHandler 

String 

NVARCHAR和NCHAR類型

NClobTypeHandler 

String 

NCLOB類型

ByteArrayTypeHandler 

byte[] 

任何兼容的字節流類型

BlobTypeHandler 

byte[] 

BLOB和LONGVARBINARY類型

DateTypeHandler 

Date(java.util)

TIMESTAMP類型

DateOnlyTypeHandler 

Date(java.util)

DATE類型

TimeOnlyTypeHandler 

Date(java.util)

TIME類型

SqlTimestampTypeHandler 

Timestamp(java.sql)

TIMESTAMP類型

SqlDateTypeHandler 

Date(java.sql)

DATE類型

SqlTimeTypeHandler 

Time(java.sql)

TIME類型

ObjectTypeHandler 

任意

其餘或未指定類型

EnumTypeHandler 

Enumeration類型

VARCHAR-任何兼容的字符串類型,做爲代碼存儲(而不是索引)。

2.五、mappers(映射配置)

映射配置能夠有多種方式,以下XML配置所示:

<!-- 將sql映射註冊到全局配置中-->
    <mappers>

        <!--
            mapper 單個註冊(mapper若是多的話,不太可能用這種方式)
                resource:引用類路徑下的文件
                url:引用磁盤路徑下的資源
                class,引用接口
            package 批量註冊(基本上使用這種方式)
                name:mapper接口與mapper.xml所在的包名
        -->

        <!-- 第一種:註冊sql映射文件-->
        <mapper resource="com/zhangguo/mapper/UserMapper.xml" />

        <!-- 第二種:註冊接口sql映射文件必須與接口同名,而且放在同一目錄下-->
        <mapper class="com.zhangguo.mapper.UserMapper" />

        <!-- 第三種:註冊基於註解的接口  基於註解   沒有sql映射文件,全部的sql都是利用註解寫在接口上-->
        <mapper class="com.zhangguo.mapper.TeacherMapper" />

        <!-- 第四種:批量註冊  須要將sql配置文件和接口放到同一目錄下-->
        <package name="com.zhangguo.mapper" />

    </mappers>

2.5.一、經過resource加載單個映射文件

    <mappers>
        <!--根據路徑註冊一個基於XML的映射器-->
        <mapper resource="mapper/studentMapper.xml"/>
    </mappers>

注意位置

2.5.2:經過mapper接口加載單個映射文件

    <!-- 經過mapper接口加載單個映射配置文件
            遵循必定的規範:須要將mapper接口類名和mapper.xml映射文件名稱保持一致,且在一個目錄中;
            上邊規範的前提是:使用的是mapper代理方法;
      -->
         <mapper class="com.mybatis.mapper.UserMapper"/> 

按照上邊的規範,將mapper.javamapper.xml放在一個目錄 ,且同名。

注意:

對於Maven項目,IntelliJ IDEA默認是不處理src/main/java中的非java文件的,不專門在pom.xml中配置<resources>是會報錯的,參考處理辦法:

<resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
</resources>

因此src/main/java中最好不要出現非java文件。實際上,將mapper.xml放在src/main/resources中比較合適。

2.5.三、批量加載mapper

<!-- 批量加載映射配置文件,mybatis自動掃描包下面的mapper接口進行加載
     遵循必定的規範:須要將mapper接口類名和mapper.xml映射文件名稱保持一致,且在一個目錄中;
     上邊規範的前提是:使用的是mapper代理方法;
      -->
<package name="com.mybatis.mapper"/> 

最後的配置文件:

<?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>
    <!--導入db.properties文件中的全部key-value數據-->
    <!--外部引入的內容將覆蓋內部定義的-->
    <properties resource="db.properties">
        <!--定義一個名稱爲driver,值爲com.mysql.jdbc.Driver的屬性-->
        <property name="mysql.driver" value="com.mysql.jdbc.Driver"></property>
    </properties>
    
    <settings>
        <!--設置是否容許緩存-->
        <setting name="cacheEnabled" value="true"/>
        <!--設置日誌輸出的目標-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <!--別名-->
    <typeAliases>
        <!--定義單個別名,指定名稱爲student,對應的類型爲com.zhangguo.mybatis02.entities.Student-->
        <!--<typeAlias type="com.zhangguo.mybatis02.entities.Student" alias="student"></typeAlias>-->
        <!--指定包名下全部的類被自動掃描並定義默認別名,
        mybatis會自動掃描包中的pojo類,自動定義別名,別名就是類名(首字母大寫或小寫均可以)-->
        <package name="com.zhangguo.mybatis02.entities"></package>
    </typeAliases>

    <!--註冊自定義的類型處理器-->
    <typeHandlers>
        <!--<typeHandler handler="" javaType="" jdbcType=""></typeHandler>-->
    </typeHandlers>
    
    <!--環境配置,default爲默認選擇的環境-->
    <environments default="development">
        <!--開發-->
        <environment id="development">
            <!--事務管理-->
            <transactionManager type="JDBC"/>
            <!--鏈接池-->
            <dataSource type="POOLED">
                <!--引用屬性${mysql.driver}-->
                <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>
        <!--運行-->
        <environment id="work">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/nfmall?useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="uchr@123"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!--根據路徑註冊一個基於XML的映射器-->
        <mapper resource="mapper/studentMapper.xml"/>
        <!--根據類型註冊一個基於註解的映射器,接口-->
        <mapper class="com.zhangguo.mybatis02.dao.StudentMapper"></mapper>
        <!--根據包名批量註冊包下全部基於註解的映射器-->
        <package name="com.zhangguo.mybatis02.dao"></package>
    </mappers>

</configuration>
View Code

3、使用接口+XML實現完整數據訪問

上一章中使用XML做爲映射器與使用接口加註解的形式分別實現了完整的數據訪問,能夠點擊《MyBatis學習總結(一)——ORM概要與MyBatis快速起步》查看,這裏綜合兩種方式實現數據訪問,各取所長,配置靈活,在代碼中不須要引用很長的id名稱,面向接口編程,示例以下:

3.一、在IDEA中建立一個Maven項目

建立成功的目錄結構以下:

3.二、添加依賴

pom.xml文件以下:

<?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.zhangguo.mybatis03</groupId>
    <artifactId>MyBatis03</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.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

添加成功效果以下:

3.三、建立POJO類

學生POJO類以下:

package com.zhangguo.mybatis03.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 + '\'' +
                '}';
    }
}

3.四、建立數據訪問接口

StudentMapper.java:

package com.zhangguo.mybatis03.dao;

import com.zhangguo.mybatis03.entities.Student;

import java.util.List;

public interface StudentMapper {
    /**
     * 根據學生編號得到學生對象
     */
    Student selectStudentById(int id);

    /**
     * 根據學生姓名得到學生集合
     */
    List<Student> selectStudentsByName(String name);

    /**
     * 添加學生
     */
    int insertStudent(Student entity);

    /**
     * 更新學生
     */
    int updateStudent(Student entity);

    /**
     * 刪除學生
     */
    int deleteStudent(int id);
}

3.五、根據接口編寫XML映射器

要求方法名與Id同名,包名與namespace同名。

在src/main/resources/mapper目錄下建立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="com.zhangguo.mybatis03.dao.StudentMapper">
    <select id="selectStudentById" resultType="Student">
        SELECT id,name,sex from student where id=#{id}
    </select>

    <select id="selectStudentsByName" 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>

3.六、添加MyBatis核心配置文件

在src/main/resources目錄下建立兩個配置文件。

mybatisCfg.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>
    <!--導入db.properties文件中的全部key-value數據-->
    <!--外部引入的內容將覆蓋內部定義的-->
    <properties resource="db.properties">
        <!--定義一個名稱爲driver,值爲com.mysql.jdbc.Driver的屬性-->
        <property name="mysql.driver" value="com.mysql.jdbc.Driver"></property>
    </properties>

    <settings>
        <!--設置是否容許緩存-->
        <setting name="cacheEnabled" value="true"/>
        <!--設置日誌輸出的目標-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <!--別名-->
    <typeAliases>
        <!--定義單個別名,指定名稱爲student,對應的類型爲com.zhangguo.mybatis02.entities.Student-->
        <!--<typeAlias type="com.zhangguo.mybatis02.entities.Student" alias="student"></typeAlias>-->
        <!--指定包名下全部的類被自動掃描並定義默認別名,
        mybatis會自動掃描包中的pojo類,自動定義別名,別名就是類名(首字母大寫或小寫均可以)-->
        <package name="com.zhangguo.mybatis03.entities"></package>
    </typeAliases>

    <!--註冊自定義的類型處理器-->
    <typeHandlers>
        <!--<typeHandler handler="" javaType="" jdbcType=""></typeHandler>-->
    </typeHandlers>

    <!--環境配置,default爲默認選擇的環境-->
    <environments default="development">
        <!--開發-->
        <environment id="development">
            <!--事務管理-->
            <transactionManager type="JDBC"/>
            <!--鏈接池-->
            <dataSource type="POOLED">
                <!--引用屬性${mysql.driver}-->
                <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>
        <!--運行-->
        <environment id="work">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/nfmall?useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="uchr@123"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!--根據路徑註冊一個基於XML的映射器-->
        <mapper resource="mapper/studentMapper.xml"/>
    </mappers>

</configuration>

db.properties文件內容以下:

##MySQL鏈接字符串
#驅動
mysql.driver=com.mysql.jdbc.Driver
#地址
mysql.url=jdbc:mysql://127.0.0.1:3306/nfmall?useUnicode=true&characterEncoding=UTF-8
#用戶名
mysql.username=root
#密碼
mysql.password=uchr@123

3.七、編寫MyBatis通用的工具類

 SqlSessionFactoryUtil.java內容以下:

package com.zhangguo.mybatis03.utils;

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;

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

    /**
     * 得到會話工廠
     *
     * */
    public static SqlSessionFactory getFactory(){
        InputStream inputStream = null;
        SqlSessionFactory sqlSessionFactory=null;
        try{
            //加載mybatisCfg.xml配置文件,轉換成輸入流
            inputStream = SqlSessionFactoryUtil.class.getClassLoader().getResourceAsStream("mybatisCfg.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();
        }
    }

}

3.八、經過MyBatis實現數據訪問

StudentDao.java內容以下:

package com.zhangguo.mybatis03.dao;

import com.zhangguo.mybatis03.entities.Student;
import com.zhangguo.mybatis03.utils.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;

import java.util.List;

public class StudentDao implements StudentMapper {

    /**
     * 根據學生編號得到學生對象
     */
    public Student selectStudentById(int id) {
        Student entity = null;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //得到一個映射器
        StudentMapper mapper=session.getMapper(StudentMapper.class);

        //查詢單個對象,指定參數爲3
        entity = mapper.selectStudentById(id);

        //關閉
        SqlSessionFactoryUtil.closeSession(session);

        return entity;
    }


    /**
     * 根據學生姓名得到學生集合
     */
    public List<Student> selectStudentsByName(String name) {
        List<Student> entities = null;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //得到一個映射器
        StudentMapper mapper=session.getMapper(StudentMapper.class);

        //查詢多個對象,指定參數
        entities =mapper.selectStudentsByName(name);
        //關閉
        SqlSessionFactoryUtil.closeSession(session);
        return entities;
    }


    /**
     * 添加學生
     */
    public int insertStudent(Student entity) {
        //影響行數
        int rows=0;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //得到一個映射器
        StudentMapper mapper=session.getMapper(StudentMapper.class);

        //執行添加
        rows = mapper.insertStudent(entity);
        //關閉
        SqlSessionFactoryUtil.closeSession(session);
        return rows;
    }

    /**
     * 更新學生
     */
    public int updateStudent(Student entity) {
        //影響行數
        int rows=0;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //得到一個映射器
        StudentMapper mapper=session.getMapper(StudentMapper.class);

        //執行更新
        rows =mapper.updateStudent(entity);
        //關閉
        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;
    }

}

最後完成的項目結構:

3.九、測試用例

在測試類上添加註解@FixMethodOrder(MethodSorters.JVM)的目的是指定測試方法按定義的順序執行。

StudentDaoTest.java以下所示: 

package com.zhangguo.mybatis03.dao;

import com.zhangguo.mybatis03.entities.Student;
import org.junit.*;
import org.junit.runners.MethodSorters;

import java.util.List;

/**
 * StudentDao Tester.
 *
 * @author <Authors name>
 * @version 1.0
 * @since <pre>09/26/2018</pre>
 */
@FixMethodOrder(MethodSorters.JVM)//指定測試方法按定義的順序執行
public class StudentDaoTest {
    StudentMapper 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 {
        Student entity=dao.selectStudentById(1);
        System.out.println(entity);
        Assert.assertNotNull(entity);
    }

    /**
     * Method: selectStudentsByName(String name)
     */
    @Test
    public void testSelectStudentsByName() throws Exception {
        List<Student> students=dao.selectStudentsByName("C");
        System.out.println(students);
        Assert.assertNotNull(students);
    }

    /**
     * Method: insertStudent
     */
    @Test
    public void testInsertStudent() throws Exception {
        Student entity=new Student();
        entity.setName("張大");
        entity.setSex("boy");

        Assert.assertEquals(1,dao.insertStudent(entity));
    }

    /**
     * Method: updateStudent
     */
    @Test
    public void testUpdateStudent() throws Exception {
        Student entity=dao.selectStudentById(11);
        entity.setName("張麗美");
        entity.setSex("girl");

        Assert.assertEquals(1,dao.updateStudent(entity));
    }

    /**
     * Method: deleteStudent
     */
    @Test
    public void testDeleteStudent() throws Exception {
        Assert.assertEquals(1,dao.deleteStudent(12));
    }
} 
View Code

3.十、測試結果

測試前的數據庫:

測試結果:

日誌:

"C:\Program Files\Java\jdk1.8.0_111\bin\java" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.2.1\lib\idea_rt.jar=2783:C:\Program Files\JetBrains\IntelliJ IDEA 2017.2.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\JetBrains\IntelliJ IDEA 2017.2.1\lib\idea_rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2017.2.1\plugins\junit\lib\junit-rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2017.2.1\plugins\junit\lib\junit5-rt.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_111\jre\lib\rt.jar;D:\Documents\Downloads\Compressed\MyBatis03\target\test-classes;D:\Documents\Downloads\Compressed\MyBatis03\target\classes;C:\Users\Administrator\.m2\repository\org\mybatis\mybatis\3.4.6\mybatis-3.4.6.jar;C:\Users\Administrator\.m2\repository\mysql\mysql-connector-java\5.1.38\mysql-connector-java-5.1.38.jar;C:\Users\Administrator\.m2\repository\junit\junit\4.11\junit-4.11.jar;C:\Users\Administrator\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar" com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 -junit4 com.zhangguo.mybatis03.dao.StudentDaoTest
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 662822946.
==>  Preparing: delete from student where id=? 
==> Parameters: 12(Integer)
<==    Updates: 1
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@2781e022]
Returned connection 662822946 to pool.
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 1045941616.
==>  Preparing: SELECT id,name,sex from student where id=? 
==> Parameters: 11(Integer)
<==    Columns: id, name, sex
<==        Row: 11, lili, secret
<==      Total: 1
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3e57cd70]
Returned connection 1045941616 to pool.
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 1540270363.
==>  Preparing: update student set name=?,sex=? where id=? 
==> Parameters: 張麗美(String), girl(String), 11(Integer)
<==    Updates: 1
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5bcea91b]
Returned connection 1540270363 to pool.
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 681384962.
==>  Preparing: insert into student(name,sex) VALUES(?,'boy') 
==> Parameters: 張大(String)
<==    Updates: 1
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@289d1c02]
Returned connection 681384962 to pool.
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 428910174.
==>  Preparing: SELECT id,name,sex from student where name like '%C%'; 
==> Parameters: 
<==    Columns: id, name, sex
<==        Row: 4, candy, secret
<==      Total: 1
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1990a65e]
Returned connection 428910174 to pool.
[Student{id=4, name='candy', sex='secret'}]
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Opening JDBC Connection
Created connection 1134612201.
==>  Preparing: SELECT id,name,sex from student where id=? 
==> Parameters: 1(Integer)
<==    Columns: id, name, sex
<==        Row: 1, rose, girl
<==      Total: 1
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@43a0cee9]
Returned connection 1134612201 to pool.
Student{id=1, name='rose', sex='girl'}

Process finished with exit code 0
View Code

測試後的數據庫:

 

4、MyBatis輸入輸出映射

4.一、輸入映射

經過parameterType指定輸入參數的類型,類型能夠是簡單類型、HashMap、POJO的包裝類型。

Mybatis的配置文件中的select,insert,update,delete有一個屬性parameter來接收mapper接口方法中的參數。能夠接收的類型有簡單類型和複雜類型,可是隻能是一個參數。這個屬性是可選的,由於Mybatis能夠經過TypeHandler來判斷傳入的參數類型,默認值是unset。

4.1.一、基本類型

各類java的基本數據類型。經常使用的有int、String、Data等

接口:

    /**
     * 根據學生編號得到學生對象
     */
    Student selectStudentById(int id);

映射:

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

測試:

    /**
     * Method: selectStudentById(int id)
     */
    @Test
    public void testSelectStudentById() throws Exception {
        Student entity=dao.selectStudentById(1);
        System.out.println(entity);
        Assert.assertNotNull(entity);
    }

結果:

用#{變量名}來取值,這裏的變量名是任意的,能夠用value或者是其它的什麼值,這裏用id是爲了便於理解,並不存在什麼對應關係的。由於java反射主只可以獲得方法參數的類型,而無從知道參數的名字的。當在動態sql中的if語句中的test傳遞參數時,就必需要用_parameter來傳遞參數了(OGNL表達式),若是你傳入id就會報錯。

4.1.二、多個參數

(一)、舊版本MyBatis使用索引號:

<select id="selectStudentsByNameOrSex" resultType="student">
    SELECT id,name,sex from student where name='%${0}%' or sex=#{1};
</select>

因爲是多參數那麼就不能使用parameterType, 改用#{index}是第幾個就用第幾個的索引,索引從0開始

注意:

若是出現錯誤:Parameter '0' not found. Available parameters are [arg1, arg0, param1, param2],請使用#{arg0}或#{param1}

注意:在MyBatis3.4.4版之後不能直接使用#{0}要使用 #{arg0}

(二)、新版本MyBatis使用索引號:

接口:

    /**
     * 根據學生姓名或性別得到學生集合
     */
    List<Student> selectStudentsByNameOrSex(String name,String sex);

映射:

<select id="selectStudentsByNameOrSex" resultType="student">
    SELECT id,name,sex from student where name like '%${arg0}%' or sex=#{param2};
</select>

方法一:arg0,arg1,arg2...
方法二:param1,param2,param3...

測試:

    /**
     * Method: selectStudentsByNameOrSex(String name, String sex)
     */
    @Test
    public void selectStudentsByNameOrSex() throws Exception {
        List<Student> students=dao.selectStudentsByNameOrSex("Candy","boy");
        System.out.println(students);
        Assert.assertNotNull(students);
    }

結果:

(三)、使用Map

接口:

    /**
     * 根據學生姓名或性別得到學生集合
     */
    List<Student> selectStudentsByNameOrSex(Map<String,Object> params);

映射:

    <select id="selectStudentsByNameOrSex" resultType="student">
        SELECT id,name,sex from student where name like '%${name}%' or sex=#{sex};
    </select>

測試:

    /**
     * Method: List<Student> selectStudentsByNameOrSex(Map<String,Object> params);
     */
    @Test
    public void selectStudentsByNameOrSex() throws Exception {
        Map<String,Object> params=new HashMap<String,Object>();
        params.put("name","Candy");
        params.put("sex","girl");
        List<Student> students=dao.selectStudentsByNameOrSex(params);

        System.out.println(students);
        Assert.assertNotNull(students);
    }

結果:

(四)、註解參數名稱:

接口:

    /**
     * 根據學生姓名或性別得到學生集合
     */
    List<Student> selectStudentsByNameOrSex(@Param("realname") String name,@Param("sex") String sex);

映射:

    <select id="selectStudentsByNameOrSex" resultType="student">
        SELECT id,name,sex from student where name like '%${realname}%' or sex=#{sex};
    </select>

測試:

    /**
     * Method: selectStudentsByNameOrSex(String name,String sex)
     */
    @Test
    public void testSelectStudentsByNameOrSex() throws Exception {
        List<Student> students=dao.selectStudentsByNameOrSex("C","boy");
        System.out.println(students);
        Assert.assertNotNull(students);
    }

結果:

4.1.三、POJO對象

各類類型的POJO,取值用#{屬性名}。這裏的屬性名是和傳入的POJO中的屬性名一一對應。

接口:

    /**
     * 添加學生
     */
    int insertStudent(Student entity);

映射:

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

測試:

    /**
     * Method: insertStudent
     */
    @Test
    public void testInsertStudent() throws Exception {
        Student entity=new Student();
        entity.setName("張明");
        entity.setSex("boy");

        Assert.assertEquals(1,dao.insertStudent(entity));
    }

結果:

若是要在if元素中測試傳入的user參數,仍然要使用_parameter來引用傳遞進來的實際參數,由於傳遞進來的User對象的名字是不可考的。若是測試對象的屬性,則直接引用屬性名字就能夠了。
測試user對象:

<if test="_parameter!= null">

測試user對象的屬性:

<if test="name!= null">

若是對象中還存在對象則須要使用${屬性名.屬性.x}方式訪問

4.1.四、Map

具體請查看4.1.2節

傳入map類型,直接經過#{keyname}就能夠引用到鍵對應的值。使用@param註釋的多個參數值也會組裝成一個map數據結構,和直接傳遞map進來沒有區別。

mapper接口:

int updateByExample(@Param("user") User user, @Param("example") UserExample example);

sql映射:

<update id="updateByExample" parameterType="map" > 

update tb_user set id = #{user.id}, ... 

<if test="_parameter != null" > 

<include refid="Update_By_Example_Where_Clause" />

</if>

</update>

注意這裏測試傳遞進來的map是否爲空,仍然使用_parameter

4.1.五、集合類型

能夠傳遞一個List或Array類型的對象做爲參數,MyBatis會自動的將List或Array對象包裝到一個Map對象中,List類型對象會使用list做爲鍵名,而Array對象會用array做爲鍵名。集合類型一般用於構造IN條件,sql映射文件中使用foreach元素來遍歷List或Array元素。

假定這裏須要實現多刪除功能,示例以下:

接口:

    /**
     * 刪除多個學生經過編號
     */
    int deleteStudents(List<Integer> ids);

映射:

    <delete id="deleteStudents">
        delete from student where id in
        <foreach collection="list" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>

collection這裏只能是list

測試:

    /**
     * Method: deleteStudents
     */
    @Test
    public void testDeleteStudents() throws Exception {
        List<Integer> ids=new ArrayList<Integer>();
        ids.add(10);
        ids.add(11);
        Assert.assertEquals(2,dao.deleteStudents(ids));
    }

結果:

固然查詢中也能夠這樣使用

public List<XXXBean> getXXXBeanList(List<String> list);  

<select id="getXXXBeanList" resultType="XXBean">
  select 字段... from XXX where id in
  <foreach item="item" index="index" collection="list" open="(" separator="," close=")">  
    #{item}  
  </foreach>  
</select>  

foreach 最後的效果是select 字段... from XXX where id in ('1','2','3','4') 

對於單獨傳遞的List或Array,在SQL映射文件中映射時,只能經過list或array來引用。可是若是對象類型有屬性的類型爲List或Array,則在sql映射文件的foreach元素中,能夠直接使用屬性名字來引用。
mapper接口: 

List<User> selectByExample(UserExample example);

sql映射文件: 

<where>
<foreach collection="oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
</where>

在這裏,UserExample有一個屬性叫oredCriteria,其類型爲List,因此在foreach元素裏直接用屬性名oredCriteria引用這個List便可。

item="criteria"表示使用criteria這個名字引用每個集合中的每個List或Array元素。

4.二、輸出映射

輸出映射主要有兩種方式指定ResultType或ResultMap,如今分別介紹一下:

4.2.一、ResultType

使用ResultType進行輸出映射,只有查詢出來的列名和pojo中的屬性名一致,該列才能夠映射成功。

若是查詢出來的列名和POJO中的屬性名所有不一致,沒有建立POJO對象。

只要查詢出來的列名和POJO中的屬性有一個一致,就會建立POJO對象。

(一)、輸出簡單類型

接口:

    /**
     * 得到學生總數
     * */
    long selectStudentsCount();

映射:

    <select id="selectStudentsCount" resultType="long">
        SELECT count(*) from student
    </select>

測試:

    /**
     * Method: selectStudentsCount()
     */
    @Test
    public void testSelectStudentsCount() throws Exception {
        Assert.assertNotEquals(0,dao.selectStudentsCount());
    }

結果:

查詢出來的結果集只有一行一列,可使用簡單類型進行輸出映射。

(二)、輸出POJO對象和POJO列表 

不論是輸出的POJO單個對象仍是一個列表(List中存放POJO),在mapper.xml中ResultType指定的類型是同樣的,但方法返回值類型不同。

輸出單個POJO對象,方法返回值是單個對象類型

接口:

    /**
     * 根據學生編號得到學生對象
     */ Student selectStudentById(int id);

映射:

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

輸出pojo對象list,方法返回值是List<POJO>

接口:

    /**
     * 根據學生姓名得到學生集合
     */ List<Student> selectStudentsByName(String name);

映射:

    <select id="selectStudentsByName" parameterType="String" resultType="student">
        SELECT id,name,sex from student where name like '%${value}%';
    </select>

生成的動態代理對象中是根據mapper.java方法的返回值類型肯定是調用selectOne(返回單個對象調用)仍是selectList(返回集合對象調用)

4.2.二、ResultMap

MyBatis中使用ResultMap完成自定義輸出結果映射,如一對多,多對多關聯關係。

問題:

假定POJO對象與表中的字段不一致,以下所示:

接口:

    /**
     * 根據性別得到學生集合
     */
    List<Stu> selectStudentsBySex(String sex);

映射:

    <select id="selectStudentsBySex" parameterType="String" resultType="stu">
        SELECT id,name,sex from student where sex=#{sex};
    </select>

測試:

    /**
     * Method: selectStudentsBySex(String sex)
     */
    @Test
    public void testSelectStudentsBySex() throws Exception {
        List<Stu> students=dao.selectStudentsBySex("boy");
        System.out.println(students);
        Assert.assertNotNull(students.get(0));
    }

結果:

 

(一)、定義並引用ResultMap

修改映射文件:

    <!--定義結果映射,id是引用時的編號需惟一,stu是最終被映射的類型-->
    <resultMap id="stuMap" type="stu">
        <!--映射結果,collumn表示列名,property表示屬性名-->
        <result column="id" property="stu_id"></result>
        <result column="name" property="stu_name"></result>
        <result column="sex" property="stu_sex"></result>
    </resultMap>
    
    <!--resultMap指定引用的映射-->
    <select id="selectStudentsBySex" parameterType="String" resultMap="stuMap">
        SELECT id,name,sex from student where sex=#{sex};
    </select>

測試結果:

(二)、使用別名

 修改映射文件:

    <select id="selectStudentsBySex" parameterType="String" resultType="stu">
      SELECT id stu_id,name stu_name,sex as stu_sex from student where sex=#{sex};
    </select>

測試結果:

4.2.三、返回Map

假定要返回id做爲key,name做爲value的Map。

接口:

    /**
     * 得到全部學生Map集合
     */
    List<Map<String,Object>> selectAllStudents();

映射:

    <resultMap id="stuKeyValueMap" type="HashMap">
        <result property="name" column="NAME"></result>
        <result property="value" column="VALUE"></result>
    </resultMap>

    <select id="selectAllStudents" resultMap="stuKeyValueMap">
        SELECT id NAME,name VALUE from student;
    </select>

測試:

   /**
     * Method: selectAllStudents()
     */
    @Test
    public void testSelectAllStudents() throws Exception {
        List<Map<String,Object>>  students=dao.selectAllStudents();
        System.out.println(students);
        Assert.assertNotNull(students);
    }

結果:

<resultMap id="pieMap"   type="HashMap">  
    <result property="value" column="VALUE" />  
    <result property="name" column="NAME" />  
</resultMap>

<select id="queryPieParam" parameterType="String" resultMap="pieMap">
    SELECT
      PLAT_NAME NAME,
        <if test='_parameter == "總量"'>
            AMOUNT VALUE
        </if>
        <if test='_parameter == "總額"'>
            TOTALS VALUE
        </if>
    FROM
        DOMAIN_PLAT_DEAL_PIE
    ORDER BY
        <if test='_parameter  == "總量"'>
            AMOUNT
        </if>
        <if test='_parameter  == "總額"'>
            TOTALS
        </if>
    ASC
</select>

resultType進行輸出映射,只有查詢出來的列名和pojo中的屬性名一致,該列才能夠映射成功。

若是查詢出來的列名和pojo的屬性名不一致,經過定義一個resultMap對列名和pojo屬性名之間做一個映射關係。

 最終完成的映射器:

<?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.zhangguo.mybatis03.dao.StudentMapper">

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

    <select id="selectStudentsCount" resultType="long">
        SELECT count(*) from student
    </select>

    <select id="selectStudentsByName" parameterType="String" resultType="student">
        SELECT id,name,sex from student where name like '%${value}%';
    </select>

    <resultMap id="stuKeyValueMap" type="HashMap">
        <result property="name" column="NAME"></result>
        <result property="value" column="VALUE"></result>
    </resultMap>

    <select id="selectAllStudents" resultMap="stuKeyValueMap">
        SELECT id NAME,name VALUE from student;
    </select>


    <!--定義結果映射,id是引用時的編號需惟一,stu是最終被映射的類型-->
    <resultMap id="stuMap" type="stu">
        <!--映射結果,collumn表示列名,property表示屬性名-->
        <result column="id" property="stu_id"></result>
        <result column="name" property="stu_name"></result>
        <result column="sex" property="stu_sex"></result>
    </resultMap>

    <!--resultMap指定引用的映射-->
    <!--<select id="selectStudentsBySex" parameterType="String" resultMap="stuMap">-->
        <!--SELECT id,name,sex from student where sex=#{sex};-->
    <!--</select>-->

    <select id="selectStudentsBySex" parameterType="String" resultType="stu">
      SELECT id stu_id,name stu_name,sex as stu_sex from student where sex=#{sex};
    </select>


    <select id="selectStudentsByNameOrSex" resultType="student">
      SELECT id,name,sex from student where name like '%${realname}%' or sex=#{sex};
    </select>

    <select id="selectStudentsByIdOrSex" resultType="student">
        SELECT id,name,sex from student where id=#{no} or sex=#{sex};
    </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>

    <delete id="deleteStudents">
        delete from student where id in
        <foreach collection="list" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>

</mapper>
View Code

 最終完成的數據訪問相似:

package com.zhangguo.mybatis03.dao;

import com.zhangguo.mybatis03.entities.Stu;
import com.zhangguo.mybatis03.entities.Student;
import com.zhangguo.mybatis03.utils.SqlSessionFactoryUtil;
import org.apache.ibatis.session.SqlSession;

import java.util.List;
import java.util.Map;

public class StudentDao implements StudentMapper {

    /**
     * 根據學生編號得到學生對象
     */
    public Student selectStudentById(int id) {
        Student entity = null;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //得到一個映射器
        StudentMapper mapper = session.getMapper(StudentMapper.class);

        //查詢單個對象,指定參數爲3
        entity = mapper.selectStudentById(id);

        //關閉
        SqlSessionFactoryUtil.closeSession(session);

        return entity;
    }

    /**
     * 得到學生總數
     */
    public long selectStudentsCount() {
        long count = 0;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //得到一個映射器
        StudentMapper mapper = session.getMapper(StudentMapper.class);

        //查詢單行單列,簡單值
        count = mapper.selectStudentsCount();

        //關閉
        SqlSessionFactoryUtil.closeSession(session);

        return count;
    }


    /**
     * 根據學生姓名得到學生集合
     */
    public List<Student> selectStudentsByName(String name) {
        List<Student> entities = null;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //得到一個映射器
        StudentMapper mapper = session.getMapper(StudentMapper.class);

        //查詢多個對象,指定參數
        entities = mapper.selectStudentsByName(name);
        //關閉
        SqlSessionFactoryUtil.closeSession(session);
        return entities;
    }

    /**
     * 得到全部學生Map集合
     *
     */
    public List<Map<String, Object>> selectAllStudents() {
        List<Map<String, Object>> entities = null;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //得到一個映射器
        StudentMapper mapper = session.getMapper(StudentMapper.class);

        //查詢多個對象,指定參數
        entities = mapper.selectAllStudents();
        //關閉
        SqlSessionFactoryUtil.closeSession(session);
        return entities;
    }

    /**
     * 根據性別得到學生集合
     *
     * @param sex
     */
    public List<Stu> selectStudentsBySex(String sex) {
        List<Stu> entities = null;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //得到一個映射器
        StudentMapper mapper = session.getMapper(StudentMapper.class);

        //查詢多個對象,指定參數
        entities = mapper.selectStudentsBySex(sex);
        //關閉
        SqlSessionFactoryUtil.closeSession(session);
        return entities;
    }

    /**
     * 根據學生姓名或性別得到學生集合
     *
     * @param name
     * @param sex
     */
    public List<Student> selectStudentsByNameOrSex(String name, String sex) {
        List<Student> entities = null;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //得到一個映射器
        StudentMapper mapper = session.getMapper(StudentMapper.class);

        //查詢多個對象,指定參數
        entities = mapper.selectStudentsByNameOrSex(name, sex);
        //關閉
        SqlSessionFactoryUtil.closeSession(session);
        return entities;
    }

    /**
     * 根據學生Id或性別得到學生集合
     *
     * @param param
     */
    public List<Student> selectStudentsByIdOrSex(Map<String, Object> param) {
        List<Student> entities = null;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //得到一個映射器
        StudentMapper mapper = session.getMapper(StudentMapper.class);

        //查詢多個對象,指定參數
        entities = mapper.selectStudentsByIdOrSex(param);
        //關閉
        SqlSessionFactoryUtil.closeSession(session);
        return entities;
    }


    /**
     * 添加學生
     */
    public int insertStudent(Student entity) {
        //影響行數
        int rows = 0;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //得到一個映射器
        StudentMapper mapper = session.getMapper(StudentMapper.class);

        //執行添加
        rows = mapper.insertStudent(entity);
        //關閉
        SqlSessionFactoryUtil.closeSession(session);
        return rows;
    }

    /**
     * 更新學生
     */
    public int updateStudent(Student entity) {
        //影響行數
        int rows = 0;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //得到一個映射器
        StudentMapper mapper = session.getMapper(StudentMapper.class);

        //執行更新
        rows = mapper.updateStudent(entity);
        //關閉
        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;
    }

    /**
     * 刪除多個學生經過編號
     *
     * @param ids
     */
    public int deleteStudents(List<Integer> ids) {
        //影響行數
        int rows = 0;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtil.openSession(true);

        //得到一個映射器
        StudentMapper mapper = session.getMapper(StudentMapper.class);

        //執行刪除
        rows = mapper.deleteStudents(ids);
        //關閉
        SqlSessionFactoryUtil.closeSession(session);
        return rows;
    }

}
View Code

 最終完成的接口:

package com.zhangguo.mybatis03.dao;

import com.zhangguo.mybatis03.entities.Stu;
import com.zhangguo.mybatis03.entities.Student;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface StudentMapper {
    /**
     * 根據學生編號得到學生對象
     */
    Student selectStudentById(int id);

    /**
     * 得到學生總數
     * */
    long selectStudentsCount();

    /**
     * 根據學生姓名得到學生集合
     */
    List<Student> selectStudentsByName(String name);


    /**
     * 得到全部學生Map集合
     */
    List<Map<String,Object>> selectAllStudents();

    /**
     * 根據性別得到學生集合
     */
    List<Stu> selectStudentsBySex(String sex);

    /**
     * 根據學生姓名或性別得到學生集合
     */
    List<Student> selectStudentsByNameOrSex(@Param("realname") String name,@Param("sex") String sex);

    /**
     * 根據學生Id或性別得到學生集合
     */
    List<Student> selectStudentsByIdOrSex(Map<String,Object> param);


    /**
     * 添加學生
     */
    int insertStudent(Student entity);

    /**
     * 更新學生
     */
    int updateStudent(Student entity);

    /**
     * 刪除學生
     */
    int deleteStudent(int id);

    /**
     * 刪除多個學生經過編號
     */
    int deleteStudents(List<Integer> ids);
}
View Code

 最終完成的測試:

package com.zhangguo.mybatis03.dao;

import com.zhangguo.mybatis03.entities.Stu;
import com.zhangguo.mybatis03.entities.Student;
import org.junit.*;
import org.junit.runners.MethodSorters;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * StudentDao Tester.
 *
 * @author <Authors name>
 * @version 1.0
 * @since <pre>09/26/2018</pre>
 */
@FixMethodOrder(MethodSorters.JVM)//指定測試方法按定義的順序執行
public class StudentDaoTest {
    StudentMapper 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 {
        Student entity=dao.selectStudentById(1);
        System.out.println(entity);
        Assert.assertNotNull(entity);
    }

    //
    /**
     * Method: selectStudentsCount()
     */
    @Test
    public void testSelectStudentsCount() throws Exception {
        Assert.assertNotEquals(0,dao.selectStudentsCount());
    }
    /**
     * Method: selectStudentsByName(String name)
     */
    @Test
    public void testSelectStudentsByName() throws Exception {
        List<Student> students=dao.selectStudentsByName("C");
        System.out.println(students);
        Assert.assertNotNull(students);
    }

    /**
     * Method: selectAllStudents()
     */
    @Test
    public void testSelectAllStudents() throws Exception {
        List<Map<String,Object>>  students=dao.selectAllStudents();
        System.out.println(students);
        Assert.assertNotNull(students);
    }

    /**
     * Method: selectStudentsBySex(String sex)
     */
    @Test
    public void testSelectStudentsBySex() throws Exception {
        List<Stu> students=dao.selectStudentsBySex("boy");
        System.out.println(students);
        Assert.assertNotNull(students.get(0));
    }


    /**
     * Method: selectStudentsByIdOrSex
     */
    @Test
    public void testSelectStudentsByNameOrSex() throws Exception {
        Map<String ,Object> param=new HashMap<String,Object>();
        param.put("no",1);
        param.put("sex","girl");
        List<Student> students=dao.selectStudentsByIdOrSex(param);
        System.out.println(students);
        Assert.assertNotNull(students);
    }

    /**
     * Method: insertStudent
     */
    @Test
    public void testInsertStudent() throws Exception {
        Student entity=new Student();
        //entity.setName("張明");
        entity.setSex("boy");

        Assert.assertEquals(1,dao.insertStudent(entity));
    }

    /**
     * Method: updateStudent
     */
    @Test
    public void testUpdateStudent() throws Exception {
        Student entity=dao.selectStudentById(11);
        //entity.setName("張麗美");
        entity.setSex("girl");

        Assert.assertEquals(1,dao.updateStudent(entity));
    }

    /**
     * Method: deleteStudent
     */
    @Test
    public void testDeleteStudent() throws Exception {
        Assert.assertEquals(1,dao.deleteStudent(12));
    }



    /**
     * Method: deleteStudents
     */
    @Test
    public void testDeleteStudents() throws Exception {
        List<Integer> ids=new ArrayList<Integer>();
        ids.add(10);
        ids.add(11);
        Assert.assertEquals(2,dao.deleteStudents(ids));
    }
} 
View Code

5、示例源代碼

https://git.coding.net/zhangguo5/MyBatis03.git

https://git.coding.net/zhangguo5/MyBatis02.git

6、視頻

https://www.bilibili.com/video/av32447485/

7、做業

一、重現上全部上課示例

二、請使用Maven多模塊+Git+MyBatis完成一個單表的管理功能,須要UI,能夠AJAX也能夠JSTL做表示層。

三、分頁,多條件組合查詢,多表鏈接(選做)

四、內部測試題(4個小時)

4.一、請實現一個簡易圖書管理系統(LibSystem),實現圖書管理功能,要求以下:(初級)

一、管理數據庫中全部圖書(Books),包含圖書編號(isbn)、書名(title)、做者(author)、價格(price)、出版日期(publishDate)

二、Maven多模塊+MySQL+Git+MyBatis+JUnit單元測試

三、表示層能夠是AJAX或JSTL

C10 R(10+10) U10 D10

 

4.二、請實現一個迷你圖書管理系統(LibSystem),實現圖書管理功能,要求以下:(中級)

一、管理數據庫中全部圖書分類(Categories),包含圖書編號(id),名稱(name)

二、管理數據庫中全部圖書(Books),包含圖書編號(isbn)、類別(categoryId,外鍵)書名(title)、做者(author)、價格(price)、出版日期(publishDate)、封面(cover)、詳細介紹(details)

三、分頁 10

四、多條件組件查詢(3個以上的條件任意組合)(高級) 10

五、多刪除 (高級) 10

六、上傳封面 (高級) 10

七、富文本編輯器 (高級) 10

相關文章
相關標籤/搜索