MyBatis學習總結(四)——MyBatis緩存與代碼生成

 1、MyBatis緩存

緩存能夠提升系統性能,能夠加快訪問速度,減輕服務器壓力,帶來更好的用戶體驗。緩存用空間換時間,好的緩存是緩存命中率高的且數據量小的。緩存是一種很是重要的技術。html

1.0、再次封裝SqlSessionFactoryUtils

爲了配置緩存的學習咱們將工具類再次封裝。java

原SqlSessionFactoryUtil工具類以下:mysql

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{
            //加載conf.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();
        }
    }

}
View Code

上面的代碼中當咱們每次獲取SQLSession時都要實例化sqlSessionFactory,效率不高。可使用單例改進:git

package com.zhangguo.mybatis03.utils;

import org.apache.ibatis.io.Resources;
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 SqlSessionFactoryUtils {

    /**會話工廠*/
    private static SqlSessionFactory factory;

    static {
        try {
            /*得到配置文件的文件流*/
           InputStream inputStream=Resources.getResourceAsStream("mybatisCfg.xml");
           //初始化工廠
            factory=new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到會話對象
     * 指定是否自動提交
     * */
    public static SqlSession openSqlSession(boolean isAutoCommit){
        return getFactory().openSession(isAutoCommit);
    }

    public static SqlSessionFactory getFactory() {
        return factory;
    }
    public static void setFactory(SqlSessionFactory factory) {
        SqlSessionFactoryUtils.factory = factory;
    }

    /**
     * 關閉會話
     * */
    public static void closeSession(SqlSession session){
        if(session!=null){
            session.close();
        }
    }
}

1.一、MyBatis緩存概要

在一個系統中查詢的頻次遠遠高於增刪改,據三方統計不一樣系統比例在9:1-7:3之間。正如大多數持久層框架同樣,MyBatis 一樣提供了一級緩存二級緩存的支持github

(1)、一級緩存基於PerpetualCache 的 HashMap本地緩存,其存儲做用域爲 Session,當 Session flush close 以後,該Session中的全部 Cache 就將清空算法

(2)、二級緩存與一級緩存其機制相同,默認也是採用 PerpetualCache,HashMap存儲,不一樣在於其存儲做用域爲 Mapper(Namespace)而且可自定義存儲源,如 Ehcache。sql

(3)、對於緩存數據更新機制,當某一個做用域(一級緩存Session/二級緩存Namespaces)的進行了 C/U/D 操做後,默認該做用域下全部 select 中的緩存將被clear。數據庫

1.二、默認MyBatis的一級緩存是開啓的

測試用例:macos

    /**緩存測試*/
    @Test
    public void cacheTest(){
        //打開一個會話,不自動提交
        SqlSession session1 = SqlSessionFactoryUtils.openSqlSession(false);
        //得到一個映射器
        StudentMapper mapper1 = session1.getMapper(StudentMapper.class);
        //查詢單個對象經過編號
        Student student1 = mapper1.selectStudentById(1);
        System.out.println(student1);
        
        Student student2 = mapper1.selectStudentById(1);
        System.out.println(student2);
        //關閉
        SqlSessionFactoryUtils.closeSession(session1);
    }

結果:apache

雖然查詢了二次,但只向數據庫發送了一次SQL請求,由於第二次是在緩存中得到的數據。

1.三、一級緩存僅在同一個會話(SQLSession)中有效

測試用例:

    /**緩存測試*/
    @Test
    public void cacheTest(){
        //打開一個會話1,不自動提交
        SqlSession session1 = SqlSessionFactoryUtils.openSqlSession(false);
        //得到一個映射器
        StudentMapper mapper1 = session1.getMapper(StudentMapper.class);
        //查詢單個對象經過編號
        Student student1 = mapper1.selectStudentById(1);
        System.out.println(student1);

        //打開一個會話2,不自動提交
        SqlSession session2 = SqlSessionFactoryUtils.openSqlSession(false);
        //得到一個映射器
        StudentMapper mapper2 = session2.getMapper(StudentMapper.class);
        Student student2 = mapper2.selectStudentById(1);
        System.out.println(student2);
        //關閉
        SqlSessionFactoryUtils.closeSession(session1);
    }

結果:

從上圖能夠看出此時並無使用緩存,向數據庫查詢了二次,由於第二次查詢使用的是新的會話,而一級緩存必須在同一個會話中。

1.四、清空一級緩存

(1)、當對錶執行增刪改時緩存將清空

測試用例:

    /**緩存測試*/
    @Test
    public void cacheTest(){
        //打開一個會話1,不自動提交
        SqlSession session1 = SqlSessionFactoryUtils.openSqlSession(false);
        //得到一個映射器
        StudentMapper mapper1 = session1.getMapper(StudentMapper.class);
        //查詢單個對象經過編號
        Student student1 = mapper1.selectStudentById(1);
        System.out.println(student1);

        //執行更新
        Student lili=new Student();
        lili.setId(5);
        lili.setSex("girl");
        mapper1.updateStudent(lili);

        Student student2 = mapper1.selectStudentById(1);
        System.out.println(student2);

        SqlSessionFactoryUtils.closeSession(session1);
    }

結果:

從日誌中能夠看出第二次查詢也發送了sql到數據庫中,並無使用緩存,是由於執行了更新操做緩存已被清空。

此時數據庫中的數據其實並未真的更新,以下所示:

由於沒有手動提交,能夠設置自動提交

/**緩存測試*/
    @Test
    public void cacheTest(){
        //打開一個會話1,不自動提交
        SqlSession session1 = SqlSessionFactoryUtils.openSqlSession(false);
        //得到一個映射器
        StudentMapper mapper1 = session1.getMapper(StudentMapper.class);
        //查詢單個對象經過編號
        Student student1 = mapper1.selectStudentById(1);
        System.out.println(student1);

        //執行更新
        Student lili=new Student();
        lili.setId(5);
        lili.setSex("girl");
        mapper1.updateStudent(lili);

        Student student2 = mapper1.selectStudentById(1);
        System.out.println(student2);

        //提交
        session1.commit();
        SqlSessionFactoryUtils.closeSession(session1);
    }
View Code

提交後的結果

(2)、手動清空

測試用例:

   /**緩存測試*/
    @Test
    public void cacheTest(){
        //打開一個會話1,不自動提交
        SqlSession session1 = SqlSessionFactoryUtils.openSqlSession(false);
        //得到一個映射器
        StudentMapper mapper1 = session1.getMapper(StudentMapper.class);
        //查詢單個對象經過編號
        Student student1 = mapper1.selectStudentById(1);
        System.out.println(student1);

        //執行手動更新
        session1.clearCache();

        Student student2 = mapper1.selectStudentById(1);
        System.out.println(student2);

        //提交
        session1.commit();
        SqlSessionFactoryUtils.closeSession(session1);
    }

結果:

從日誌中能夠看到第二次查詢並未使用緩存由於執行了手動清空緩存,沒有緩存可用則再次查詢數據庫。

小結:當Session flush或close以後,該Session中的全部 Cache 就將清空;執行CUD也將會自動清空;手動清空;

1.五、開啓二級緩存

默認二級緩存是不開啓的,須要手動進行配置

1.5.一、全局開關

默認是true,若是它配成false,其他各個Mapper XML文件配成支持cache也沒用。

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

1.5.二、單個Mapper XML映射文件開關

默認Mapper XML映射文件是不採用cache。在配置文件加一行就能夠支持cache:

<?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">

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

能夠在開啓二級緩存時候,手動配置一些屬性

<cache eviction="LRU" flushInterval="100000" size="1024" readOnly="true"/>

各個屬性意義以下:

  • eviction:緩存回收策略
    - LRU:最少使用原則,移除最長時間不使用的對象
    - FIFO:先進先出原則,按照對象進入緩存順序進行回收
    - SOFT:軟引用,移除基於垃圾回收器狀態和軟引用規則的對象
    - WEAK:弱引用,更積極的移除移除基於垃圾回收器狀態和弱引用規則的對象
  • flushInterval:刷新時間間隔,單位爲毫秒,這裏配置的100毫秒。若是不配置,那麼只有在進行數據庫修改操做纔會被動刷新緩存區
  • size:引用額數目,表明緩存最多能夠存儲的對象個數
  • readOnly:是否只讀,若是爲true,則全部相同的sql語句返回的是同一個對象(有助於提升性能,但併發操做同一條數據時,可能不安全),若是設置爲false,則相同的sql,後面訪問的是cache的clone副本。

1.5.三、Mapper statement開關

Mapper XML文件配置支持cache後,文件中全部的Mapper statement就支持了。此時要個別對待某條,須要:

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

能夠在Mapper的具體方法下設置對二級緩存的訪問意願:

  • useCache配置

    ​ 若是一條語句每次都須要最新的數據,就意味着每次都須要從數據庫中查詢數據,能夠把這個屬性設置爲false,如:

<select id="selectAll" useCache="false">
  • 刷新緩存(就是清空緩存)

    ​ 二級緩存默認會在insert、update、delete操做後刷新緩存,能夠手動配置不更新緩存,以下:

<update id="updateById" flushCache="false" />

1.5.四、實現可序列化接口

 若是未實現可序列化接口,會引起異常。

修改POJO對象,增長實現可序列化接口:

package com.zhangguo.mybatis03.entities;

import java.io.Serializable;

/**
 * 學生實體
 */
public class Student implements Serializable {
    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 + '\'' +
                '}';
    }
}
View Code

1.5.五、注意事項

一、若是readOnly爲false,此時要結果集對象是可序列化的。
<cache readOnly="false"/>
二、在SqlSession未關閉以前,若是對於一樣條件進行重複查詢,此時採用的是local session cache,而不是上面說的這些cache。
三、MyBatis緩存查詢到的結果集對象,而非結果集數據,是將映射的POJO對象集合緩存起來。
四、面對必定規模的數據量,內置的cache方式就派不上用場了;
五、對查詢結果集作緩存並非MyBatis框架擅長的,它專心作的應該是sql mapper。採用此框架的Application去構建緩存更合理,好比採用Redis、Ehcache、OSCache、Memcached等

當咱們的配置文件配置了cacheEnabled=true時,就會開啓二級緩存,二級緩存是mapper級別的,也就說不一樣的sqlsession使用同一個mapper查詢是,查詢到的數據多是另外一個sqlsession作相同操做留下的緩存。

查詢數據的順序爲:二級緩存 -> 一級緩存 -> 數據庫

1.六、二級緩存測試

默認狀況下一級緩存只在同一個會話中有效:

用例:

    /**緩存測試*/
    @Test
    public void cacheTest(){
        //打開一個會話1,不自動提交
        SqlSession session1 = SqlSessionFactoryUtils.openSqlSession(false);
        //得到一個映射器1
        StudentMapper mapper1 = session1.getMapper(StudentMapper.class);
        //查詢單個對象經過編號
        Student student1 = mapper1.selectStudentById(1);
        System.out.println(student1);
        
        //打開一個會話2,不自動提交
        SqlSession session2 = SqlSessionFactoryUtils.openSqlSession(false);
        //得到一個映射器2
        StudentMapper mapper2 = session2.getMapper(StudentMapper.class);
        //查詢單個對象經過編號
        Student student2 = mapper2.selectStudentById(1);
        System.out.println(student2);

        SqlSessionFactoryUtils.closeSession(session1);
        SqlSessionFactoryUtils.closeSession(session2);
    }

結果:

若是須要將範圍擴大到同一個namespace中有效可使用二級緩存:

用例:

    /**緩存測試*/
    @Test
    public void cacheTest(){
        //打開一個會話1,不自動提交
        SqlSession session1 = SqlSessionFactoryUtils.openSqlSession(false);
        //得到一個映射器1
        StudentMapper mapper1 = session1.getMapper(StudentMapper.class);
        //查詢單個對象經過編號
        Student student1 = mapper1.selectStudentById(1);
        System.out.println(student1);

        //必須手動提交,不然無效
        session1.commit();

        //打開一個會話2,不自動提交
        SqlSession session2 = SqlSessionFactoryUtils.openSqlSession(false);
        //得到一個映射器2
        StudentMapper mapper2 = session2.getMapper(StudentMapper.class);
        //查詢單個對象經過編號
        Student student2 = mapper2.selectStudentById(1);
        System.out.println(student2);

        SqlSessionFactoryUtils.closeSession(session1);
        SqlSessionFactoryUtils.closeSession(session2);
    }

結果:

 

若是不手動提交查詢結果也不會緩存成功。

使用兩個不一樣的SqlSession對象去執行相同查詢條件的查詢,第二次查詢時不會再發送SQL語句,而是直接從緩存中取出數據

1.七、二級緩存小結

  1. 映射語句文件中的全部select語句將會被緩存。

  2. 映射語句文件中的全部insert,update和delete語句會刷新緩存。

  3. 緩存會使用Least Recently Used(LRU,最近最少使用的)算法來收回。

  4. 緩存會根據指定的時間間隔來刷新。

  5. 緩存會存儲1024個對象

cache標籤經常使用屬性:

<cache 
eviction="FIFO"  <!--回收策略爲先進先出-->
flushInterval="60000" <!--自動刷新時間60s-->
size="512" <!--最多緩存512個引用對象-->
readOnly="true"/> <!--只讀-->

2、MyBatis-Generator代碼生成

2.一、在Intellij IDEA建立maven項目

這裏建立了一個Maven項目,未使用骨架。

2.二、添加依賴

在maven項目的pom.xml 添加mybatis-generator-maven-plugin 插件

<?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.mybatis06</groupId>
    <artifactId>MyBatis06</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>
        <!-- mybatis-generator-core 反向生成java代碼-->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.5</version>
        </dependency>
    </dependencies>


    <!--mybatis 代碼生成插件-->
    <build>
        <finalName>MyBatis06</finalName>
        <plugins>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.2</version>
                <configuration>
                    <verbose>true</verbose>
                    <overwrite>true</overwrite>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2.三、配置生成參數

在maven項目下的src/main/resources 目錄下創建名爲 generatorConfig.xml的配置文件,做爲mybatis-generator-maven-plugin 插件的執行目標:

<?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>

    <!--導入屬性配置 -->
    <properties resource="db.properties"></properties>

    <!--指定特定數據庫的jdbc驅動jar包的位置 -->
    <classPathEntry location="${mysql.driverLocation}"/>

    <context id="default" targetRuntime="MyBatis3">

        <!-- optional,旨在建立class時,對註釋進行控制 -->
        <commentGenerator>
            <property name="suppressDate" value="true" />
        </commentGenerator>

        <!--jdbc的數據庫鏈接 -->
        <jdbcConnection driverClass="${mysql.driver}" connectionURL="${mysql.url}" userId="${mysql.username}" password="${mysql.password}">
        </jdbcConnection>

        <!-- 非必需,類型處理器,在數據庫類型和java類型之間的轉換控制-->
        <javaTypeResolver >
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!-- Model模型生成器,用來生成含有主鍵key的類,記錄類 以及查詢Example類
            targetPackage     指定生成的model生成所在的包名
            targetProject     指定在該項目下所在的路徑
        -->
        <javaModelGenerator targetPackage="com.zhangguo.mybatis06.entities" targetProject="src/main/java">
            <!-- 是否對model添加 構造函數 -->
            <property name="constructorBased" value="true"/>

            <!-- 是否容許子包,即targetPackage.schemaName.tableName -->
            <property name="enableSubPackages" value="false"/>

            <!-- 創建的Model對象是否 不可改變  即生成的Model對象不會有 setter方法,只有構造方法 -->
            <property name="immutable" value="true"/>

            <!-- 給Model添加一個父類 -->
            <property name="rootClass" value="com.zhangguo.mybatis06.entities.BaseEntity"/>

            <!-- 是否對類CHAR類型的列的數據進行trim操做 -->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>

        <!--Mapper映射文件生成所在的目錄 爲每個數據庫的表生成對應的SqlMap文件 -->
        <sqlMapGenerator targetPackage="com.zhangguo.mybatis06.mapper" targetProject="src/main/resources">
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>


        <!-- 客戶端代碼,生成易於使用的針對Model對象和XML配置文件 的代碼
                type="ANNOTATEDMAPPER",生成Java Model 和基於註解的Mapper對象
                type="MIXEDMAPPER",生成基於註解的Java Model 和相應的Mapper對象
                type="XMLMAPPER",生成SQLMap XML文件和獨立的Mapper接口
        -->
        <javaClientGenerator targetPackage="com.zhangguo.mybatis06.dao" targetProject="src/main/java" type="MIXEDMAPPER">
            <property name="enableSubPackages" value=""/>
            <!--
                    定義Maper.java 源代碼中的ByExample() 方法的可視性,可選的值有:
                    public;
                    private;
                    protected;
                    default
                    注意:若是 targetRuntime="MyBatis3",此參數被忽略
             -->
            <property name="exampleMethodVisibility" value=""/>
            <!--
               方法名計數器
              Important note: this property is ignored if the target runtime is MyBatis3.
             -->
            <property name="methodNameCalculator" value=""/>

            <!--
              爲生成的接口添加父接口
             -->
            <property name="rootInterface" value=""/>
        </javaClientGenerator>



        <table tableName="student" schema="nfmall"></table>
        <table tableName="category" schema="nfmall"></table>
        <table tableName="goods" schema="nfmall"></table>
    </context>
</generatorConfiguration>

這裏的屬性資源文件與mybatis共用db.propities文件

##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
#驅動位置
mysql.driverLocation=E:\\NF\\Java\\JDBC\\mysql-connector-java-5.1.47\\mysql-connector-java-5.1.47.jar

參數配置文件一:

<?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>

    <!-- 本地數據庫驅動程序jar包的全路徑 -->
    <classPathEntry location=""/>

    <context id="context" targetRuntime="MyBatis3">
        <commentGenerator>
            <property name="suppressAllComments" value="false"/>
            <property name="suppressDate" value="true"/>
        </commentGenerator>

        <!-- 數據庫的相關配置 -->
        <jdbcConnection driverClass="" connectionURL="" userId="" password=""/>

        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>

        <!-- 實體類生成的位置 -->
        <javaModelGenerator targetPackage="目標包" targetProject="目標項目classpath">
            <property name="enableSubPackages" value="false"/>
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>

        <!-- *Mapper.xml 文件的位置 -->
        <sqlMapGenerator targetPackage="目標包" targetProject="目標項目classpath">
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>

        <!-- Mapper 接口文件的位置 -->
        <javaClientGenerator targetPackage="目標包" targetProject="目標項目classpath" type="XMLMAPPER">
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>

        <!-- 相關表的配置 -->
        <table tableName="表名" enableCountByExample="false" enableDeleteByExample="false" enableSelectByExample="false"
               enableUpdateByExample="false"/>
    </context>
</generatorConfiguration>
View Code

參考配置文件二:

<?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>  
    <!--導入屬性配置 -->  
    <properties resource="generator.properties"></properties>  
  
    <!--指定特定數據庫的jdbc驅動jar包的位置 -->  
    <classPathEntry location="${jdbc.driverLocation}"/>  
  
    <context id="default" targetRuntime="MyBatis3">  
  
  
        <!-- optional,旨在建立class時,對註釋進行控制 -->  
        <commentGenerator>  
            <property name="suppressDate" value="true" />  
        </commentGenerator>  
  
  
        <!--jdbc的數據庫鏈接 -->  
        <jdbcConnection driverClass="${jdbc.driverClass}" connectionURL="${jdbc.connectionURL}" userId="${jdbc.userId}" password="${jdbc.password}">  
        </jdbcConnection>  
  
  
  
        <!-- 非必需,類型處理器,在數據庫類型和java類型之間的轉換控制-->  
        <javaTypeResolver >  
            <property name="forceBigDecimals" value="false" />  
        </javaTypeResolver>  
  
        <!-- Model模型生成器,用來生成含有主鍵key的類,記錄類 以及查詢Example類  
            targetPackage     指定生成的model生成所在的包名  
            targetProject     指定在該項目下所在的路徑  
        -->  
        <javaModelGenerator targetPackage="org.louis.hometutor.po" targetProject="src/main/java">  
            <!-- 是否對model添加 構造函數 -->  
            <property name="constructorBased" value="true"/>  
  
            <!-- 是否容許子包,即targetPackage.schemaName.tableName -->  
            <property name="enableSubPackages" value="false"/>  
  
            <!-- 創建的Model對象是否 不可改變  即生成的Model對象不會有 setter方法,只有構造方法 -->  
            <property name="immutable" value="true"/>  
  
            <!-- 給Model添加一個父類 -->  
            <property name="rootClass" value="com.foo.louis.Hello"/>  
  
            <!-- 是否對類CHAR類型的列的數據進行trim操做 -->  
            <property name="trimStrings" value="true"/>  
        </javaModelGenerator>  
  
        <!--Mapper映射文件生成所在的目錄 爲每個數據庫的表生成對應的SqlMap文件 -->  
        <sqlMapGenerator targetPackage="org.louis.hometutor.domain" targetProject="src/main/java">  
            <property name="enableSubPackages" value="false"/>  
        </sqlMapGenerator>  
  
  
        <!-- 客戶端代碼,生成易於使用的針對Model對象和XML配置文件 的代碼  
                type="ANNOTATEDMAPPER",生成Java Model 和基於註解的Mapper對象  
                type="MIXEDMAPPER",生成基於註解的Java Model 和相應的Mapper對象  
                type="XMLMAPPER",生成SQLMap XML文件和獨立的Mapper接口  
        -->  
        <javaClientGenerator targetPackage="com.foo.tourist.dao" targetProject="src/main/java" type="MIXEDMAPPER">  
            <property name="enableSubPackages" value=""/>  
            <!--  
                    定義Maper.java 源代碼中的ByExample() 方法的可視性,可選的值有:  
                    public;  
                    private;  
                    protected;  
                    default  
                    注意:若是 targetRuntime="MyBatis3",此參數被忽略  
             -->  
            <property name="exampleMethodVisibility" value=""/>  
            <!--  
                                           方法名計數器  
              Important note: this property is ignored if the target runtime is MyBatis3.  
             -->  
            <property name="methodNameCalculator" value=""/>  
  
            <!-- 
                                                爲生成的接口添加父接口 
             -->  
            <property name="rootInterface" value=""/>  
  
        </javaClientGenerator>  
  
  
  
        <table tableName="lession" schema="louis">  
  
            <!-- optional   , only for mybatis3 runtime  
                 自動生成的鍵值(identity,或者序列值)  
               若是指定此元素,MBG將會生成<selectKey>元素,而後將此元素插入到SQL Map的<insert> 元素之中  
               sqlStatement 的語句將會返回新的值  
               若是是一個自增主鍵的話,你可使用預約義的語句,或者添加自定義的SQL語句. 預約義的值以下:  
                  Cloudscape    This will translate to: VALUES IDENTITY_VAL_LOCAL()  
                  DB2:      VALUES IDENTITY_VAL_LOCAL()  
                  DB2_MF:       SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1  
                  Derby:        VALUES IDENTITY_VAL_LOCAL()  
                  HSQLDB:   CALL IDENTITY()  
                  Informix:     select dbinfo('sqlca.sqlerrd1') from systables where tabid=1  
                  MySql:        SELECT LAST_INSERT_ID()  
                  SqlServer:    SELECT SCOPE_IDENTITY()  
                  SYBASE:   SELECT @@IDENTITY  
                  JDBC:     This will configure MBG to generate code for MyBatis3 suport of JDBC standard generated keys. 
This is a database independent method of obtaining the value from identity columns.  
                  identity: 自增主鍵  If true, then the column is flagged as an identity column and the generated <selectKey> 
element will be placed after the insert (for an identity column). If false, then the generated <selectKey> will be placed before
 the insert (typically for a sequence).  
  
            -->  
            <generatedKey column="" sqlStatement="" identity="" type=""/>  
  
  
            <!-- optional.  
                    列的命名規則:  
                    MBG使用 <columnRenamingRule> 元素在計算列名的對應 名稱以前,先對列名進行重命名,  
                    做用:通常須要對BUSI_CLIENT_NO 前的BUSI_進行過濾  
                    支持正在表達式  
                     searchString 表示要被換掉的字符串  
                     replaceString 則是要換成的字符串,默認狀況下爲空字符串,可選  
            -->  
            <columnRenamingRule searchString="" replaceString=""/>  
  
  
  
            <!-- optional.告訴 MBG 忽略某一列  
                    column,須要忽略的列  
                    delimitedColumnName:true ,匹配column的值和數據庫列的名稱 大小寫徹底匹配,false 忽略大小寫匹配  
                    是否限定表的列名,即固定表列在Model中的名稱  
            -->  
            <ignoreColumn column="PLAN_ID"  delimitedColumnName="true" />  
  
  
            <!--optional.覆蓋MBG對Model 的生成規則  
                 column: 數據庫的列名  
                 javaType: 對應的Java數據類型的徹底限定名  
                 在必要的時候能夠覆蓋由JavaTypeResolver計算獲得的java數據類型. For some databases, this is necessary to handle "odd" 
database types (e.g. MySql's unsigned bigint type should be mapped to java.lang.Object).  
                 jdbcType:該列的JDBC數據類型(INTEGER, DECIMAL, NUMERIC, VARCHAR, etc.),該列能夠覆蓋由JavaTypeResolver計算獲得的Jdbc類型,
對某些數據庫而言,對於處理特定的JDBC 驅動癖好 頗有必要(e.g. DB2's LONGVARCHAR type should be mapped to VARCHAR for iBATIS).  
                 typeHandler:  
  
            -->  
            <columnOverride column="" javaType=""    jdbcType="" typeHandler=""  delimitedColumnName="" />  
  
        </table>  
    </context>  
</generatorConfiguration>  
View Code

屬性資源文件:

jdbc.driverLocation=E:\\NF\\Java\\JDBC\\mysql-connector-java-5.1.47\\mysql-connector-java-5.1.47.jar
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.connectionURL=jdbc:mysql://127.0.0.1:3306/nfmall?useUnicode=true&characterEncoding=UTF-8
jdbc.userId=root
jdbc.password=uchr@123
View Code

這裏使用了外置的配置文件generator.properties,能夠將一下屬性配置到properties文件之中,增長配置的靈活性:

項目目錄以下:

2.四、執行生成

在Maven Projects中找到Plugins->mybatis-generator->mybatis-generator:generate

點擊運行,而後不出意外的話,會在控制檯輸出:

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building MyBatis06 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- mybatis-generator-maven-plugin:1.3.2:generate (default-cli) @ MyBatis06 ---
[INFO] Connecting to the Database
[INFO] Introspecting table nfmall.student
log4j:WARN No appenders could be found for logger (org.mybatis.generator.internal.db.DatabaseIntrospector).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
[INFO] Introspecting table nfmall.category
[INFO] Introspecting table nfmall.goods
[INFO] Generating Example class for table student
[INFO] Generating Record class for table student
[INFO] Generating Mapper Interface for table student
[INFO] Generating SQL Map for table student
[INFO] Generating Example class for table category
[INFO] Generating Record class for table category
[INFO] Generating Mapper Interface for table category
[INFO] Generating SQL Map for table category
[INFO] Generating Example class for table goods
[INFO] Generating Record class for table goods
[INFO] Generating Mapper Interface for table goods
[INFO] Generating SQL Map for table goods
[INFO] Saving file StudentMapper.xml
[INFO] Saving file CategoryMapper.xml
[INFO] Saving file GoodsMapper.xml
[INFO] Saving file StudentExample.java
[INFO] Saving file Student.java
[INFO] Saving file StudentMapper.java
[INFO] Saving file CategoryExample.java
[INFO] Saving file Category.java
[INFO] Saving file CategoryMapper.java
[INFO] Saving file GoodsExample.java
[INFO] Saving file Goods.java
[INFO] Saving file GoodsMapper.java
[WARNING] Root class com.zhangguo.mybatis06.entities.BaseEntity cannot be loaded, checking for member overrides is disabled for this class 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.845 s
[INFO] Finished at: 2018-10-10T09:51:45+08:00
[INFO] Final Memory: 11M/162M
[INFO] ------------------------------------------------------------------------
View Code

看到BUILD SUCCESS,則大功告成,若是有錯誤的話,因爲添加了-e 選項,會把具體的詳細錯誤信息打印出來的,根據錯誤信息修改便可。

生成結果:

2.五、使用生成的代碼

一、MyBatis會話工具類

package com.zhangguo.mybatis06.utils;

import org.apache.ibatis.io.Resources;
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 SqlSessionFactoryUtils {

    /**會話工廠*/
    private static SqlSessionFactory factory;

    static {
        try {
            /*得到配置文件的文件流*/
           InputStream inputStream=Resources.getResourceAsStream("mybatisCfg.xml");
           //初始化工廠
            factory=new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到會話對象
     * 指定是否自動提交
     * */
    public static SqlSession openSqlSession(boolean isAutoCommit){
        return getFactory().openSession(isAutoCommit);
    }

    public static SqlSessionFactory getFactory() {
        return factory;
    }
    public static void setFactory(SqlSessionFactory factory) {
        SqlSessionFactoryUtils.factory = factory;
    }

    /**
     * 關閉會話
     * */
    public static void closeSession(SqlSession session){
        if(session!=null){
            session.close();
        }
    }
}
View Code

二、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>
    <!--導入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="com/zhangguo/mybatis06/mapper/studentMapper.xml"/>

    </mappers>

</configuration>
View Code

三、測試用例

package test;

import com.zhangguo.mybatis06.dao.StudentMapper;
import com.zhangguo.mybatis06.entities.Student;
import com.zhangguo.mybatis06.entities.StudentExample;
import com.zhangguo.mybatis06.utils.SqlSessionFactoryUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class StudentTest {
    /***
     * List<Student> selectByExample(StudentExample example);
     */
    @Test
    public void testSelectByExample(){

        List<Student> entities = null;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtils.openSqlSession(true);

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

        StudentExample studentExample=new StudentExample();
        //查詢名字中含a
        studentExample.createCriteria().andNameLike("%a%");

        //查詢多個對象,指定參數
        entities = mapper.selectByExample(studentExample);
        //關閉
        SqlSessionFactoryUtils.closeSession(session);

    }

}

測試結果:

3、MyBatis-GUI代碼生成器mybatis-generator-gui

3.一、概要

源碼地址:https://github.com/zouzg/mybatis-generator-gui

mybatis-generator-gui是基於mybatis generator開發一款界面工具, 本工具可使你很是容易及快速生成Mybatis的Java POJO文件及數據庫Mapping文件。

3.二、核心特性

  • 按照界面步驟輕鬆生成代碼,省去XML繁瑣的學習與配置過程
  • 保存數據庫鏈接與Generator配置,每次代碼生成輕鬆搞定
  • 內置經常使用插件,好比分頁插件
  • 把數據庫中表列的註釋生成爲Java實體的註釋,生成的實體清晰明瞭
  • 可選的去除掉對版本管理不友好的註釋,這樣新增或刪除字段從新生成的文件比較過來清楚
  • 目前已經支持Mysql、Mysql八、Oracle、PostgreSQL與SQL Server,暫不對其餘非主流數據庫提供支持。

3.三、要求

本工具因爲使用了Java 8的衆多特性,因此要求JDK 1.8.0.60以上版本,另外JDK 1.9暫時還不支持。

3.四、下載

你能夠從本連接下載本工具: https://github.com/astarring/mybatis-generator-gui/releases

3.五、啓動本軟件

  • 方法一: 自助構建(注意項目名稱須要根據實例狀況修改
    git clone https://github.com/astarring/mybatis-generator-gui
    cd mybatis-generator-gui
    mvn jfx:jar
    cd target/jfx/app/
    java -jar mybatis-generator-gui.jar

 

  • 方法二: IDE中運行

Eclipse or IntelliJ IDEA中啓動, 找到com.zzg.mybatis.generator.MainUI類並運行就能夠了

  • 方法三:打包爲本地原生應用,雙擊快捷方式便可啓動,方便快捷

    若是不想打包後的安裝包logo爲Java的灰色的茶杯,須要在pom文件裏將對應操做系統平臺的圖標註釋放開

    #<icon>${project.basedir}/package/windows/mybatis-generator-gui.ico</icon>爲windows
    #<icon>${project.basedir}/package/macosx/mybatis-generator-gui.icns</icon>爲mac
    mvn jfx:native

 

​ 另外須要注意,windows系統打包成exe的話須要安裝WiXToolset3+的環境;因爲打包後會把jre打入安裝包,兩個平臺均100M左右,體積較大請自行打包;打包後的安裝包在target/jfx/native目錄下

3.六、注意事項

  • 本自動生成代碼工具只適合生成單表的增刪改查,對於須要作數據庫聯合查詢的,請自行寫新的XML與Mapper;
  • 部分系統在中文輸入方法時輸入框中沒法輸入文字,請切換成英文輸入法;
  • 若是不明白對應字段或選項是什麼意思的時候,把光標放在對應字段或Label上停留一會而後若是有解釋會出現解釋;

3.七、文檔

更多詳細文檔請參考本庫的Wiki

3.八、代碼生成示例

3.8.一、建立一個Maven項目

3.8.二、下載源代碼並使用IDEA打開

下載地址:https://github.com/zouzg/mybatis-generator-gui/releases

解壓後引入到IDEA中

找到MainUI類

3.8.三、運行程序

3.8.四、鏈接到數據

 

3.8.五、生成代碼

3.8.六、使用生成的代碼

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.zhangguo.mybatis05</groupId>
    <artifactId>MyBatis05</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>

工具類:

package com.zhangguo.mybatis05.utils;

import org.apache.ibatis.io.Resources;
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 SqlSessionFactoryUtils {

    /**會話工廠*/
    private static SqlSessionFactory factory;

    static {
        try {
            /*得到配置文件的文件流*/
           InputStream inputStream=Resources.getResourceAsStream("mybatisCfg.xml");
           //初始化工廠
            factory=new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到會話對象
     * 指定是否自動提交
     * */
    public static SqlSession openSqlSession(boolean isAutoCommit){
        return getFactory().openSession(isAutoCommit);
    }

    public static SqlSessionFactory getFactory() {
        return factory;
    }
    public static void setFactory(SqlSessionFactory factory) {
        SqlSessionFactoryUtils.factory = factory;
    }

    /**
     * 關閉會話
     * */
    public static void closeSession(SqlSession session){
        if(session!=null){
            session.close();
        }
    }
}

核心配置文件:

<?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="com/zhangguo/mybatis05/StudentMapper.xml"/>
    </mappers>

</configuration>
View Code

POJO:

package com.zhangguo.mybatis05.entities;

import java.io.Serializable;

/**
 * @author 
 */
public class Student implements Serializable {
    private Integer id;

    private String name;

    private String sex;

    private static final long serialVersionUID = 1L;

    public Integer getId() {
        return id;
    }

    public void setId(Integer 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 boolean equals(Object that) {
        if (this == that) {
            return true;
        }
        if (that == null) {
            return false;
        }
        if (getClass() != that.getClass()) {
            return false;
        }
        Student other = (Student) that;
        return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId()))
            && (this.getName() == null ? other.getName() == null : this.getName().equals(other.getName()))
            && (this.getSex() == null ? other.getSex() == null : this.getSex().equals(other.getSex()));
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((getId() == null) ? 0 : getId().hashCode());
        result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
        result = prime * result + ((getSex() == null) ? 0 : getSex().hashCode());
        return result;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(getClass().getSimpleName());
        sb.append(" [");
        sb.append("Hash = ").append(hashCode());
        sb.append(", id=").append(id);
        sb.append(", name=").append(name);
        sb.append(", sex=").append(sex);
        sb.append(", serialVersionUID=").append(serialVersionUID);
        sb.append("]");
        return sb.toString();
    }
}
View Code

參數:

package com.zhangguo.mybatis05.entities;

import java.util.ArrayList;
import java.util.List;

public class StudentExample {
    protected String orderByClause;

    protected boolean distinct;

    protected List<Criteria> oredCriteria;

    private Integer limit;

    private Integer offset;

    public StudentExample() {
        oredCriteria = new ArrayList<Criteria>();
    }

    public void setOrderByClause(String orderByClause) {
        this.orderByClause = orderByClause;
    }

    public String getOrderByClause() {
        return orderByClause;
    }

    public void setDistinct(boolean distinct) {
        this.distinct = distinct;
    }

    public boolean isDistinct() {
        return distinct;
    }

    public List<Criteria> getOredCriteria() {
        return oredCriteria;
    }

    public void or(Criteria criteria) {
        oredCriteria.add(criteria);
    }

    public Criteria or() {
        Criteria criteria = createCriteriaInternal();
        oredCriteria.add(criteria);
        return criteria;
    }

    public Criteria createCriteria() {
        Criteria criteria = createCriteriaInternal();
        if (oredCriteria.size() == 0) {
            oredCriteria.add(criteria);
        }
        return criteria;
    }

    protected Criteria createCriteriaInternal() {
        Criteria criteria = new Criteria();
        return criteria;
    }

    public void clear() {
        oredCriteria.clear();
        orderByClause = null;
        distinct = false;
    }

    public void setLimit(Integer limit) {
        this.limit = limit;
    }

    public Integer getLimit() {
        return limit;
    }

    public void setOffset(Integer offset) {
        this.offset = offset;
    }

    public Integer getOffset() {
        return offset;
    }

    protected abstract static class GeneratedCriteria {
        protected List<Criterion> criteria;

        protected GeneratedCriteria() {
            super();
            criteria = new ArrayList<Criterion>();
        }

        public boolean isValid() {
            return criteria.size() > 0;
        }

        public List<Criterion> getAllCriteria() {
            return criteria;
        }

        public List<Criterion> getCriteria() {
            return criteria;
        }

        protected void addCriterion(String condition) {
            if (condition == null) {
                throw new RuntimeException("Value for condition cannot be null");
            }
            criteria.add(new Criterion(condition));
        }

        protected void addCriterion(String condition, Object value, String property) {
            if (value == null) {
                throw new RuntimeException("Value for " + property + " cannot be null");
            }
            criteria.add(new Criterion(condition, value));
        }

        protected void addCriterion(String condition, Object value1, Object value2, String property) {
            if (value1 == null || value2 == null) {
                throw new RuntimeException("Between values for " + property + " cannot be null");
            }
            criteria.add(new Criterion(condition, value1, value2));
        }

        public Criteria andIdIsNull() {
            addCriterion("id is null");
            return (Criteria) this;
        }

        public Criteria andIdIsNotNull() {
            addCriterion("id is not null");
            return (Criteria) this;
        }

        public Criteria andIdEqualTo(Integer value) {
            addCriterion("id =", value, "id");
            return (Criteria) this;
        }

        public Criteria andIdNotEqualTo(Integer value) {
            addCriterion("id <>", value, "id");
            return (Criteria) this;
        }

        public Criteria andIdGreaterThan(Integer value) {
            addCriterion("id >", value, "id");
            return (Criteria) this;
        }

        public Criteria andIdGreaterThanOrEqualTo(Integer value) {
            addCriterion("id >=", value, "id");
            return (Criteria) this;
        }

        public Criteria andIdLessThan(Integer value) {
            addCriterion("id <", value, "id");
            return (Criteria) this;
        }

        public Criteria andIdLessThanOrEqualTo(Integer value) {
            addCriterion("id <=", value, "id");
            return (Criteria) this;
        }

        public Criteria andIdIn(List<Integer> values) {
            addCriterion("id in", values, "id");
            return (Criteria) this;
        }

        public Criteria andIdNotIn(List<Integer> values) {
            addCriterion("id not in", values, "id");
            return (Criteria) this;
        }

        public Criteria andIdBetween(Integer value1, Integer value2) {
            addCriterion("id between", value1, value2, "id");
            return (Criteria) this;
        }

        public Criteria andIdNotBetween(Integer value1, Integer value2) {
            addCriterion("id not between", value1, value2, "id");
            return (Criteria) this;
        }

        public Criteria andNameIsNull() {
            addCriterion("name is null");
            return (Criteria) this;
        }

        public Criteria andNameIsNotNull() {
            addCriterion("name is not null");
            return (Criteria) this;
        }

        public Criteria andNameEqualTo(String value) {
            addCriterion("name =", value, "name");
            return (Criteria) this;
        }

        public Criteria andNameNotEqualTo(String value) {
            addCriterion("name <>", value, "name");
            return (Criteria) this;
        }

        public Criteria andNameGreaterThan(String value) {
            addCriterion("name >", value, "name");
            return (Criteria) this;
        }

        public Criteria andNameGreaterThanOrEqualTo(String value) {
            addCriterion("name >=", value, "name");
            return (Criteria) this;
        }

        public Criteria andNameLessThan(String value) {
            addCriterion("name <", value, "name");
            return (Criteria) this;
        }

        public Criteria andNameLessThanOrEqualTo(String value) {
            addCriterion("name <=", value, "name");
            return (Criteria) this;
        }

        public Criteria andNameLike(String value) {
            addCriterion("name like", value, "name");
            return (Criteria) this;
        }

        public Criteria andNameNotLike(String value) {
            addCriterion("name not like", value, "name");
            return (Criteria) this;
        }

        public Criteria andNameIn(List<String> values) {
            addCriterion("name in", values, "name");
            return (Criteria) this;
        }

        public Criteria andNameNotIn(List<String> values) {
            addCriterion("name not in", values, "name");
            return (Criteria) this;
        }

        public Criteria andNameBetween(String value1, String value2) {
            addCriterion("name between", value1, value2, "name");
            return (Criteria) this;
        }

        public Criteria andNameNotBetween(String value1, String value2) {
            addCriterion("name not between", value1, value2, "name");
            return (Criteria) this;
        }

        public Criteria andSexIsNull() {
            addCriterion("sex is null");
            return (Criteria) this;
        }

        public Criteria andSexIsNotNull() {
            addCriterion("sex is not null");
            return (Criteria) this;
        }

        public Criteria andSexEqualTo(String value) {
            addCriterion("sex =", value, "sex");
            return (Criteria) this;
        }

        public Criteria andSexNotEqualTo(String value) {
            addCriterion("sex <>", value, "sex");
            return (Criteria) this;
        }

        public Criteria andSexGreaterThan(String value) {
            addCriterion("sex >", value, "sex");
            return (Criteria) this;
        }

        public Criteria andSexGreaterThanOrEqualTo(String value) {
            addCriterion("sex >=", value, "sex");
            return (Criteria) this;
        }

        public Criteria andSexLessThan(String value) {
            addCriterion("sex <", value, "sex");
            return (Criteria) this;
        }

        public Criteria andSexLessThanOrEqualTo(String value) {
            addCriterion("sex <=", value, "sex");
            return (Criteria) this;
        }

        public Criteria andSexLike(String value) {
            addCriterion("sex like", value, "sex");
            return (Criteria) this;
        }

        public Criteria andSexNotLike(String value) {
            addCriterion("sex not like", value, "sex");
            return (Criteria) this;
        }

        public Criteria andSexIn(List<String> values) {
            addCriterion("sex in", values, "sex");
            return (Criteria) this;
        }

        public Criteria andSexNotIn(List<String> values) {
            addCriterion("sex not in", values, "sex");
            return (Criteria) this;
        }

        public Criteria andSexBetween(String value1, String value2) {
            addCriterion("sex between", value1, value2, "sex");
            return (Criteria) this;
        }

        public Criteria andSexNotBetween(String value1, String value2) {
            addCriterion("sex not between", value1, value2, "sex");
            return (Criteria) this;
        }
    }

    /**
     */
    public static class Criteria extends GeneratedCriteria {

        protected Criteria() {
            super();
        }
    }

    public static class Criterion {
        private String condition;

        private Object value;

        private Object secondValue;

        private boolean noValue;

        private boolean singleValue;

        private boolean betweenValue;

        private boolean listValue;

        private String typeHandler;

        public String getCondition() {
            return condition;
        }

        public Object getValue() {
            return value;
        }

        public Object getSecondValue() {
            return secondValue;
        }

        public boolean isNoValue() {
            return noValue;
        }

        public boolean isSingleValue() {
            return singleValue;
        }

        public boolean isBetweenValue() {
            return betweenValue;
        }

        public boolean isListValue() {
            return listValue;
        }

        public String getTypeHandler() {
            return typeHandler;
        }

        protected Criterion(String condition) {
            super();
            this.condition = condition;
            this.typeHandler = null;
            this.noValue = true;
        }

        protected Criterion(String condition, Object value, String typeHandler) {
            super();
            this.condition = condition;
            this.value = value;
            this.typeHandler = typeHandler;
            if (value instanceof List<?>) {
                this.listValue = true;
            } else {
                this.singleValue = true;
            }
        }

        protected Criterion(String condition, Object value) {
            this(condition, value, null);
        }

        protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
            super();
            this.condition = condition;
            this.value = value;
            this.secondValue = secondValue;
            this.typeHandler = typeHandler;
            this.betweenValue = true;
        }

        protected Criterion(String condition, Object value, Object secondValue) {
            this(condition, value, secondValue, null);
        }
    }
}
View Code

映射器:

<?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.mybatis05.mapper.StudentMapper">
  <resultMap id="BaseResultMap" type="com.zhangguo.mybatis05.entities.Student">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="name" jdbcType="VARCHAR" property="name" />
    <result column="sex" jdbcType="CHAR" property="sex" />
  </resultMap>
  <sql id="Example_Where_Clause">
    <where>
      <foreach collection="oredCriteria" item="criteria" separator="or">
        <if test="criteria.valid">
          <trim prefix="(" prefixOverrides="and" suffix=")">
            <foreach collection="criteria.criteria" item="criterion">
              <choose>
                <when test="criterion.noValue">
                  and ${criterion.condition}
                </when>
                <when test="criterion.singleValue">
                  and ${criterion.condition} #{criterion.value}
                </when>
                <when test="criterion.betweenValue">
                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
                </when>
                <when test="criterion.listValue">
                  and ${criterion.condition}
                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
                    #{listItem}
                  </foreach>
                </when>
              </choose>
            </foreach>
          </trim>
        </if>
      </foreach>
    </where>
  </sql>
  <sql id="Update_By_Example_Where_Clause">
    <where>
      <foreach collection="example.oredCriteria" item="criteria" separator="or">
        <if test="criteria.valid">
          <trim prefix="(" prefixOverrides="and" suffix=")">
            <foreach collection="criteria.criteria" item="criterion">
              <choose>
                <when test="criterion.noValue">
                  and ${criterion.condition}
                </when>
                <when test="criterion.singleValue">
                  and ${criterion.condition} #{criterion.value}
                </when>
                <when test="criterion.betweenValue">
                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
                </when>
                <when test="criterion.listValue">
                  and ${criterion.condition}
                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
                    #{listItem}
                  </foreach>
                </when>
              </choose>
            </foreach>
          </trim>
        </if>
      </foreach>
    </where>
  </sql>
  <sql id="Base_Column_List">
    id, name, sex
  </sql>
  <select id="selectByExample" parameterType="com.zhangguo.mybatis05.entities.StudentExample" resultMap="BaseResultMap">
    select
    <if test="distinct">
      distinct
    </if>
    <include refid="Base_Column_List" />
    from student
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
    <if test="orderByClause != null">
      order by ${orderByClause}
    </if>
    <if test="limit != null">
      <if test="offset != null">
        limit ${offset}, ${limit}
      </if>
      <if test="offset == null">
        limit ${limit}
      </if>
    </if>
  </select>
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from student
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from student
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <delete id="deleteByExample" parameterType="com.zhangguo.mybatis05.entities.StudentExample">
    delete from student
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
  </delete>
  <insert id="insert" parameterType="com.zhangguo.mybatis05.entities.Student">
    insert into student (id, name, sex)
    values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{sex,jdbcType=CHAR})
  </insert>
  <insert id="insertSelective" parameterType="com.zhangguo.mybatis05.entities.Student">
    insert into student
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="name != null">
        name,
      </if>
      <if test="sex != null">
        sex,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=INTEGER},
      </if>
      <if test="name != null">
        #{name,jdbcType=VARCHAR},
      </if>
      <if test="sex != null">
        #{sex,jdbcType=CHAR},
      </if>
    </trim>
  </insert>
  <select id="countByExample" parameterType="com.zhangguo.mybatis05.entities.StudentExample" resultType="java.lang.Long">
    select count(*) from student
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
  </select>
  <update id="updateByExampleSelective" parameterType="map">
    update student
    <set>
      <if test="record.id != null">
        id = #{record.id,jdbcType=INTEGER},
      </if>
      <if test="record.name != null">
        name = #{record.name,jdbcType=VARCHAR},
      </if>
      <if test="record.sex != null">
        sex = #{record.sex,jdbcType=CHAR},
      </if>
    </set>
    <if test="_parameter != null">
      <include refid="Update_By_Example_Where_Clause" />
    </if>
  </update>
  <update id="updateByExample" parameterType="map">
    update student
    set id = #{record.id,jdbcType=INTEGER},
      name = #{record.name,jdbcType=VARCHAR},
      sex = #{record.sex,jdbcType=CHAR}
    <if test="_parameter != null">
      <include refid="Update_By_Example_Where_Clause" />
    </if>
  </update>
  <update id="updateByPrimaryKeySelective" parameterType="com.zhangguo.mybatis05.entities.Student">
    update student
    <set>
      <if test="name != null">
        name = #{name,jdbcType=VARCHAR},
      </if>
      <if test="sex != null">
        sex = #{sex,jdbcType=CHAR},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.zhangguo.mybatis05.entities.Student">
    update student
    set name = #{name,jdbcType=VARCHAR},
      sex = #{sex,jdbcType=CHAR}
    where id = #{id,jdbcType=INTEGER}
  </update>
</mapper>
View Code

接口:

package com.zhangguo.mybatis05.mapper;

import com.zhangguo.mybatis05.entities.Student;
import com.zhangguo.mybatis05.entities.StudentExample;
import java.util.List;
import org.apache.ibatis.annotations.Param;

public interface StudentMapper {
    long countByExample(StudentExample example);

    int deleteByExample(StudentExample example);

    int deleteByPrimaryKey(Integer id);

    int insert(Student record);

    int insertSelective(Student record);

    List<Student> selectByExample(StudentExample example);

    Student selectByPrimaryKey(Integer id);

    int updateByExampleSelective(@Param("record") Student record, @Param("example") StudentExample example);

    int updateByExample(@Param("record") Student record, @Param("example") StudentExample example);

    int updateByPrimaryKeySelective(Student record);

    int updateByPrimaryKey(Student record);
}
View Code

數據訪問類:

package com.zhangguo.mybatis05.dao;

import com.zhangguo.mybatis05.entities.Student;
import com.zhangguo.mybatis05.entities.StudentExample;
import com.zhangguo.mybatis05.utils.SqlSessionFactoryUtils;
import com.zhangguo.mybatis05.mapper.StudentMapper;
import org.apache.ibatis.session.SqlSession;

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

public class StudentDao implements StudentMapper {


    public long countByExample(StudentExample example) {
        return 0;
    }

    public int deleteByExample(StudentExample example) {
        return 0;
    }

    public int deleteByPrimaryKey(Integer id) {
        return 0;
    }

    public int insert(Student record) {
        return 0;
    }

    public int insertSelective(Student record) {
        return 0;
    }

    public List<Student> selectByExample(StudentExample example) {
        List<Student>  entities = null;
        //打開一個會話
        SqlSession session = SqlSessionFactoryUtils.openSqlSession(true);

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

        //查詢多個對象
        entities = mapper.selectByExample(example);

        //關閉
        SqlSessionFactoryUtils.closeSession(session);

        return entities;
    }

    public Student selectByPrimaryKey(Integer id) {
        return null;
    }

    public int updateByExampleSelective(Student record, StudentExample example) {
        return 0;
    }

    public int updateByExample(Student record, StudentExample example) {
        return 0;
    }

    public int updateByPrimaryKeySelective(Student record) {
        return 0;
    }

    public int updateByPrimaryKey(Student record) {
        return 0;
    }
}
View Code

單元測試:

package com.zhangguo.mybatis05.dao;

import com.zhangguo.mybatis05.entities.Student;
import com.zhangguo.mybatis05.entities.StudentExample;
import org.junit.Test;
import org.junit.Before;
import org.junit.After;

import java.util.List;

/**
 * StudentDao Tester.
 *
 * @author <Authors name>
 * @version 1.0
 * @since <pre>10/09/2018</pre>
 */
public class StudentDaoTest {

    StudentDao dao;

    @Before
    public void before() throws Exception {
        dao = new StudentDao();
    }

    @After
    public void after() throws Exception {
    }

    /**
     * Method: countByExample(StudentExample example)
     */
    @Test
    public void testCountByExample() throws Exception {
//TODO: Test goes here... 
    }

    /**
     * Method: deleteByExample(StudentExample example)
     */
    @Test
    public void testDeleteByExample() throws Exception {
//TODO: Test goes here... 
    }

    /**
     * Method: deleteByPrimaryKey(Integer id)
     */
    @Test
    public void testDeleteByPrimaryKey() throws Exception {
//TODO: Test goes here... 
    }

    /**
     * Method: insert(Student record)
     */
    @Test
    public void testInsert() throws Exception {
//TODO: Test goes here... 
    }

    /**
     * Method: insertSelective(Student record)
     */
    @Test
    public void testInsertSelective() throws Exception {
//TODO: Test goes here... 
    }

    /**
     * Method: selectByExample(StudentExample example)
     */
    @Test
    public void testSelectByExample() throws Exception {
        StudentExample se = new StudentExample();

        se.createCriteria().andIdBetween(3, 5);

        List<Student> students = dao.selectByExample(se);
        System.out.println(students);
    }

    /**
     * Method: selectByPrimaryKey(Integer id)
     */
    @Test
    public void testSelectByPrimaryKey() throws Exception {
//TODO: Test goes here... 
    }

    /**
     * Method: updateByExampleSelective(Student record, StudentExample example)
     */
    @Test
    public void testUpdateByExampleSelective() throws Exception {
//TODO: Test goes here... 
    }

    /**
     * Method: updateByExample(Student record, StudentExample example)
     */
    @Test
    public void testUpdateByExample() throws Exception {
//TODO: Test goes here... 
    }

    /**
     * Method: updateByPrimaryKeySelective(Student record)
     */
    @Test
    public void testUpdateByPrimaryKeySelective() throws Exception {
//TODO: Test goes here... 
    }

    /**
     * Method: updateByPrimaryKey(Student record)
     */
    @Test
    public void testUpdateByPrimaryKey() throws Exception {
//TODO: Test goes here... 
    }


} 
View Code

運行結果:

其它GUI工具:

https://github.com/spawpaw/mybatis-generator-gui-extension

mybatis-generator-gui-extension是一個爲MybatisGenerator編寫的圖形化界面,爲實體/Example/Mapper提供了豐富的擴展。

https://github.com/xialeistudio/mybatis-generator-gui
可視化mybatis生成工具

[https://www.oschina.net/p/mybatis-generator-gui]

4、示例源代碼

https://git.dev.tencent.com/zhangguo5/MyBatis06.git

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

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

5、視頻

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

6、大做業 

概述:

在中國雲南有一個美麗的地方叫瑞麗,那裏盛產玉飾,爲了發展網絡經濟打開銷路,有一家叫瑞麗玉源的公司搭建了一個電子商務網站,要求網站中能夠按多種條件對商品進行搜索,能夠同時按照多個條件進行過濾,包括:品牌、價格、顏色、水種、鑲嵌、寓意和掛件類型。

功能需求:

一、要展現的數據已給出,在素材與數據\Data文件夾下有MSSQL Server數據庫SouthMall、SQL腳本與Excel格式的數據,使用其中任意方式能夠得到須要的數據。

二、數據庫中有一個名爲Products的商品表,表結構如表3-1所示:

序號

列名

說明

數據類型

長度

小數位

標識

主鍵

容許空

1

Id

編號

int

4

0

 

2

Name

商品名稱

nvarchar

255

0

 

 

3

Color

顏色

nvarchar

500

0

 

 

4

BrandId

品牌

int

4

0

 

 

5

InLayId

鑲嵌

Int

4

0

 

 

6

MoralId

寓意

Int

4

0

 

 

7

IceTypeId

種地

Int

4

0

 

 

8

HangTypeId

掛件類型

int

4

0

 

 

9

MarketPrice

市場價格

float

8

0

 

 

10

MyPrice

商城價格

float

8

0

 

 

11

Picture

圖片

nvarchar

255

0

 

 

表3-1

請將Color、Brand、InLay、Moral、IceType、HangType做成外鍵,拆分紅7張表

三、默認狀態爲全部條件都選擇所有,如圖3-1所示,即展現全部商品;

圖 3-1

四、當用戶點擊不一樣的條件時能夠進行多種組合過濾出相應結果,被選擇條件項應該高亮顯示,而這時不該該勾選所有(這裏使用了兩張圖片,一張是選擇所有checked.jpg,一張是未選擇所有unchecked.jpg,存放在素材與數據/UI圖片目錄中)如圖3-2所示;

 

圖3-2 

技術實現:

一、爲了考慮用戶體驗變換條件時不能刷新整頁,可考慮使用AJAX。jQuery庫文件已存放在素材與數據/Scripts目錄下,請不要使用ASP.NET AJAX技術(微軟封裝的服務器AJAX技術)。

二、搜索條件應該根據數據庫動態生成,價格除外。

三、若是使用ASP.NET WebForms技術實現,頁面中不能出現ViewState(頁面狀態),請禁用控件與頁面的狀態(EnableViewState="false")。

四、可使用任意B/S技術,如.NET,Java或PHP平臺下的Web技術。

五、除指定要求外,不對UI做特殊要求,如色彩、佈局與字體等,基本規整就能夠。UI用到的全部素材已保存在素材與數據文件夾下。

六、數據訪問方式不做限制,可使用任意ORM框架或數據庫訪問組件,如JDB、MyBatis、Hibernate、LINQ to SQL/Entity、Entity Framework、ADO.NET等。

普通:

分頁

後臺添加

模塊塊、Maven、Git

高級:

在普通的基礎上增長多字段排序(能夠選擇排序類型與升降序)

CRUD

 素材下載:https://git.dev.tencent.com/zhangguo5/MyBatis06.git

相關文章
相關標籤/搜索