緩存能夠提升系統性能,能夠加快訪問速度,減輕服務器壓力,帶來更好的用戶體驗。緩存用空間換時間,好的緩存是緩存命中率高的且數據量小的。緩存是一種很是重要的技術。html
爲了配置緩存的學習咱們將工具類再次封裝。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(); } } }
上面的代碼中當咱們每次獲取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(); } } }
在一個系統中查詢的頻次遠遠高於增刪改,據三方統計不一樣系統比例在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。數據庫
測試用例: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請求,由於第二次是在緩存中得到的數據。
測試用例:
/**緩存測試*/ @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)、當對錶執行增刪改時緩存將清空
測試用例:
/**緩存測試*/ @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); }
提交後的結果
(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也將會自動清空;手動清空;
默認二級緩存是不開啓的,須要手動進行配置:
默認是true,若是它配成false,其他各個Mapper XML文件配成支持cache也沒用。
<settings> <!--設置是否容許緩存--> <setting name="cacheEnabled" value="true"/> <!--設置日誌輸出的目標--> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings>
默認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"/>
各個屬性意義以下:
<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" />
若是未實現可序列化接口,會引起異常。
修改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 + '\'' + '}'; } }
<cache readOnly="false"/>
當咱們的配置文件配置了cacheEnabled=true時,就會開啓二級緩存,二級緩存是mapper級別的,也就說不一樣的sqlsession使用同一個mapper查詢是,查詢到的數據多是另外一個sqlsession作相同操做留下的緩存。
查詢數據的順序爲:二級緩存 -> 一級緩存 -> 數據庫
默認狀況下一級緩存只在同一個會話中有效:
用例:
/**緩存測試*/ @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. 映射語句文件中的全部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"/> <!--只讀-->
這裏建立了一個Maven項目,未使用骨架。
在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>
在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>
參考配置文件二:
<?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>
屬性資源文件:
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
這裏使用了外置的配置文件generator.properties,能夠將一下屬性配置到properties文件之中,增長配置的靈活性:
項目目錄以下:
在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] ------------------------------------------------------------------------
看到BUILD SUCCESS,則大功告成,若是有錯誤的話,因爲添加了-e 選項,會把具體的詳細錯誤信息打印出來的,根據錯誤信息修改便可。
生成結果:
一、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(); } } }
二、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&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>
三、測試用例
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); } }
測試結果:
源碼地址:https://github.com/zouzg/mybatis-generator-gui
mybatis-generator-gui是基於mybatis generator開發一款界面工具, 本工具可使你很是容易及快速生成Mybatis的Java POJO文件及數據庫Mapping文件。
本工具因爲使用了Java 8的衆多特性,因此要求JDK 1.8.0.60以上版本,另外JDK 1.9暫時還不支持。
你能夠從本連接下載本工具: https://github.com/astarring/mybatis-generator-gui/releases
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
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目錄下
更多詳細文檔請參考本庫的Wiki
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&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>
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(); } }
參數:
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); } } }
映射器:
<?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>
接口:
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); }
數據訪問類:
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; } }
單元測試:
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... } }
運行結果:
其它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]
https://git.dev.tencent.com/zhangguo5/MyBatis06.git
https://git.coding.net/zhangguo5/MyBatis03.git
https://git.coding.net/zhangguo5/MyBatis02.git
https://www.bilibili.com/video/av32447485/
概述:
在中國雲南有一個美麗的地方叫瑞麗,那裏盛產玉飾,爲了發展網絡經濟打開銷路,有一家叫瑞麗玉源的公司搭建了一個電子商務網站,要求網站中能夠按多種條件對商品進行搜索,能夠同時按照多個條件進行過濾,包括:品牌、價格、顏色、水種、鑲嵌、寓意和掛件類型。
功能需求:
一、要展現的數據已給出,在素材與數據\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