第1章MyBatis框架配置文件詳解
1.1 typeHandlers類型轉換器
每當MyBatis 設置參數到PreparedStatement 或者從ResultSet 結果集中取得值時,就會使用TypeHandler 來處理數據庫類型與java 類型之間轉換。下表描述了默認
TypeHandlers

1.1.1 自定義類型轉換器
假設表中字段是int類型,而實體類與之對應的屬性是boolean類型,此時可以采用自定義類型轉換器進行對應
(1)實體類
1 package com.chenyanbin.beans; 2 3 public class Dept { 4 private Integer deptNo; 5 private String dname; 6 private String loc; 7 private boolean flag; 8 public Integer getDeptNo() { 9 return deptNo; 10 } 11 public boolean isFlag() { 12 return flag; 13 } 14 public void setFlag(boolean flag) { 15 this.flag = flag; 16 } 17 public void setDeptNo(Integer deptNo) { 18 this.deptNo = deptNo; 19 } 20 public String getDname() { 21 return dname; 22 } 23 public void setDname(String dname) { 24 this.dname = dname; 25 } 26 public String getLoc() { 27 return loc; 28 } 29 public void setLoc(String loc) { 30 this.loc = loc; 31 } 32 }
(2) 表中字段

(3) 開發自定義類型轉換器:MyTypeHandler.java
繼承並實現接口:TypeHandler.java
1 package com.chenyanbin.util; 2 3 import java.sql.CallableStatement; 4 import java.sql.PreparedStatement; 5 import java.sql.ResultSet; 6 import java.sql.SQLException; 7 8 import org.apache.ibatis.jdbc.Null; 9 import org.apache.ibatis.type.JdbcType; 10 import org.apache.ibatis.type.TypeHandler; 11 /* 12 * setParameter:這個方法在生成SQL語句時才被調用 13 * 14 * getResult:查詢結束之后,在將ResultSet數據行轉換為實體類對象時,通知TypeHandler將當前數據行某個字段轉換為何種類型 15 * 16 * 17 */ 18 public class MyTypeHandler implements TypeHandler { 19 20 public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException { 21 if (parameter==null) { //dept.flag=null insertsql flag設置0 22 ps.setInt(i, 0); 23 return; 24 } 25 Boolean flag=(Boolean)parameter; 26 if (flag==true) { 27 ps.setInt(i, 1); 28 } 29 else { 30 ps.setInt(i, 0); 31 } 32 } 33 34 public Object getResult(ResultSet rs, String columnName) throws SQLException { 35 int flag = rs.getInt(columnName); //1 or 0 36 Boolean myFlag=Boolean.FALSE; 37 if (flag==1) { 38 myFlag=Boolean.TRUE; 39 } 40 return myFlag; 41 } 42 43 public Object getResult(ResultSet rs, int columnIndex) throws SQLException { 44 // TODO Auto-generated method stub 45 return null; 46 } 47 48 public Object getResult(CallableStatement cs, int columnIndex) throws SQLException { 49 // TODO Auto-generated method stub 50 return null; 51 } 52 53 }
(4) 在MyBatis核心配置文件注冊自定義類型轉換器:
myBatis-config.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <configuration> 6 <!-- 屬性配置 --> 7 <properties resource="config.properties"></properties> 8 <!-- 別名配置 --> 9 <typeAliases> 10 <package name="com.chenyanbin.beans" /> 11 <package name="com.chenyanbin.dao" /> 12 </typeAliases> 13 <!-- 類型處理器 --> 14 <typeHandlers> 15 <!-- 從java中的Boolean轉jdbc中的NUMERIC --> 16 <typeHandler handler="com.chenyanbin.util.MyTypeHandler" 17 javaType="Boolean" jdbcType="NUMERIC" /> 18 </typeHandlers> 19 <!-- 環境配置 --> 20 <environments default="development"> 21 <!-- 環境配置 --> 22 <environment id="development"> 23 <!-- 事務管理器 --> 24 <transactionManager type="JDBC"></transactionManager> 25 <!-- 數據源 --> 26 <dataSource type="pooled"> 27 <property name="driver" value="${jdbc.driver}" /> 28 <property name="url" value="${jdbc.url}" /> 29 <property name="username" value="${jdbc.username}" /> 30 <property name="password" value="${jdbc.password}" /> 31 </dataSource> 32 </environment> 33 </environments> 34 <!-- 映射器 --> 35 <mappers> 36 <package name="com.chenyanbin.dao" /> 37 </mappers> 38 </configuration>
config.properties
1 jdbc.driver=com.mysql.jdbc.Driver 2 jdbc.url=jdbc:mysql://localhost:3306/sam 3 jdbc.username=root 4 jdbc.password=root
(5) 創建接口:DeptMapper.java
1 package com.chenyanbin.dao; 2 3 import java.util.List; 4 import com.chenyanbin.beans.Dept; 5 6 public interface DeptMapper { 7 public void deptSave(Dept dept); 8 9 public List<Dept> deptFind(); 10 }
(6) DeptMapper.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.chenyanbin.dao.DeptMapper"> 6 <insert id="deptSave"> 7 insert into dept (DEPTNO,DNAME,LOC,flag) 8 values(#{deptNo},#{dname},#{loc},#{flag}) 9 </insert> 10 <select id="deptFind" resultType="Dept"> 11 select deptNo,dname,loc,flag from dept 12 </select> 13 </mapper>
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <configuration> 6 <!-- 屬性配置 --> 7 <properties resource="config.properties"></properties> 8 <!-- 別名配置 --> 9 <typeAliases> 10 <package name="com.chenyanbin.beans" /> 11 <package name="com.chenyanbin.dao" /> 12 </typeAliases> 13 <!-- 環境配置 --> 14 <environments default="development"> 15 <!-- 環境配置 --> 16 <environment id="development"> 17 <!-- 事務管理器 --> 18 <transactionManager type="JDBC"></transactionManager> 19 <!-- 數據源 --> 20 <dataSource type="pooled"> 21 <property name="driver" value="${jdbc.driver}" /> 22 <property name="url" value="${jdbc.url}" /> 23 <property name="username" value="${jdbc.username}" /> 24 <property name="password" value="${jdbc.password}" /> 25 </dataSource> 26 </environment> 27 </environments> 28 <!-- 映射器 --> 29 <mappers> 30 <package name="com.chenyanbin.dao" /> 31 </mappers> 32 </configuration>
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.chenyanbin.dao.DeptMapper"> 6 <insert id="deptSave"> 7 insert into dept (DEPTNO,DNAME,LOC,flag) 8 values(#{deptNo},#{dname},#{loc},#{flag}) 9 </insert> 10 <resultMap type="dept" id="deptMap"> 11 <result column="flag" property="flag" typeHandler="com.chenyanbin.util.MyTypeHandler"/> 12 </resultMap> 13 <select id="deptFind" resultType="Dept"> 14 select deptNo,dname,loc,flag from dept 15 </select> 16 </mapper>
(7) 執行單元測試:TestMain_01.java
1 package com.chenyanbin.test; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.List; 6 import org.apache.ibatis.io.Resources; 7 import org.apache.ibatis.session.SqlSession; 8 import org.apache.ibatis.session.SqlSessionFactory; 9 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 10 import org.junit.After; 11 import org.junit.Before; 12 import org.junit.Test; 13 import com.chenyanbin.beans.Dept; 14 import com.chenyanbin.dao.DeptMapper; 15 16 public class TestMain_01 { 17 private SqlSession session; 18 19 @Before 20 public void Start() { 21 try { 22 InputStream inputStream = Resources.getResourceAsStream("myBatis-config.xml"); 23 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); 24 session = factory.openSession(); 25 } catch (Exception e) { 26 e.printStackTrace(); 27 } 28 } 29 30 @After 31 public void end() { 32 if (session == null) { 33 session.close(); 34 } 35 } 36 37 @Test 38 public void test01() throws IOException { 39 Dept d2 = new Dept(); 40 d2.setDname("上海事業部"); 41 d2.setLoc("上海"); 42 d2.setFlag(false); 43 session.insert("deptSave", d2); 44 session.commit(); 45 session.close(); 46 } 47 48 @Test 49 public void test02() { 50 DeptMapper dao=session.getMapper(DeptMapper.class); 51 List<Dept> deptList=dao.deptFind(); 52 System.out.println("ok"); 53 } 54 55 }
(8) 項目目錄結構

1.2 objectFactory 對象工廠
MyBatis 每次創建結果對象的新實例時,它都會使用一個對象工廠(ObjectFactory)實例來完成。 默認的對象工廠需要做的僅僅是實例化目標類,要么通過默認構造方法,要么在參數映射存在的時候通過參數構造方法來實例化。 如果想覆蓋對象工廠的默認行為,則可以通過創建自己的對象工廠來實現。
1.2.1 自定義對象工廠
表結構:dept

實體類:Dept.java
1 package com.chenyanbin.beans; 2 3 public class Dept { 4 private Integer deptNo; 5 private String dname; 6 private String loc; 7 private Boolean flag; 8 private String country; 9 public String getCountry() { 10 return country; 11 } 12 public void setCountry(String country) { 13 this.country = country; 14 } 15 public Integer getDeptNo() { 16 return deptNo; 17 } 18 public Boolean getFlag() { 19 return flag; 20 } 21 public void setFlag(Boolean flag) { 22 this.flag = flag; 23 } 24 public void setDeptNo(Integer deptNo) { 25 this.deptNo = deptNo; 26 } 27 public String getDname() { 28 return dname; 29 } 30 public void setDname(String dname) { 31 this.dname = dname; 32 } 33 public String getLoc() { 34 return loc; 35 } 36 public void setLoc(String loc) { 37 this.loc = loc; 38 } 39 }
(1) 繼承與DefaultObjectFactory:MyObjectFactory.java
1 package com.chenyanbin.util; 2 3 import org.apache.ibatis.reflection.factory.DefaultObjectFactory; 4 5 import com.chenyanbin.beans.Dept; 6 7 public class MyObjectFactory extends DefaultObjectFactory { 8 9 @Override 10 public Object create(Class type) {// 重新定義Dept類實例對象創建規則,其他類實例對象創建規則不想改變 11 if (Dept.class == type) { 12 // 依靠父類提供create方法創建Dept對象 13 Dept dept = (Dept) super.create(type); 14 // 設置自定義規則 15 dept.setCountry("China"); 16 return dept; 17 } 18 return super.create(type); 19 } 20 21 }
(2) 在MyBatis核心文件中注冊自定義工廠
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <configuration> 6 <!-- 屬性配置 --> 7 <properties resource="config.properties"></properties> 8 <!-- 別名配置 --> 9 <typeAliases> 10 <package name="com.chenyanbin.beans" /> 11 <package name="com.chenyanbin.dao" /> 12 </typeAliases> 13 <!-- ObjectFactory對象工廠 --> 14 <objectFactory type="com.chenyanbin.util.MyObjectFactory"></objectFactory> 15 <!-- 類型處理器 --> 16 <!-- <typeHandlers> 17 從java中的Boolean轉jdbc中的NUMERIC 18 <typeHandler handler="com.chenyanbin.util.MyTypeHandler" 19 javaType="Boolean" jdbcType="NUMERIC" /> 20 </typeHandlers> --> 21 <!-- 環境配置 --> 22 <environments default="development"> 23 <!-- 環境配置 --> 24 <environment id="development"> 25 <!-- 事務管理器 --> 26 <transactionManager type="JDBC"></transactionManager> 27 <!-- 數據源 --> 28 <dataSource type="pooled"> 29 <property name="driver" value="${jdbc.driver}" /> 30 <property name="url" value="${jdbc.url}" /> 31 <property name="username" value="${jdbc.username}" /> 32 <property name="password" value="${jdbc.password}" /> 33 </dataSource> 34 </environment> 35 </environments> 36 <!-- 映射器 --> 37 <mappers> 38 <package name="com.chenyanbin.dao" /> 39 </mappers> 40 </configuration>
1.3 Plugins 攔截器
攔截器的一個作用就是我們可以攔截某些方法的調用,我們可以選擇在這些被攔截的方法執行前后加上某些邏輯,也可以在執行這些被攔截的方法時執行自己的邏輯而不再執行被攔截的方法。Mybatis攔截器設計的一個初衷就是為了供用戶在某些時候可以實現自己的邏輯而不必去動Mybatis固有的邏輯。打個比方,對於Executor,Mybatis中有幾種實現:BatchExecutor、ReuseExecutor、SimpleExecutor和CachingExecutor。這個時候如果你覺得這幾種實現對於Executor接口的query方法都不能滿足你的要求,那怎么辦呢?是要去改源碼嗎?當然不。我們可以建立一個Mybatis攔截器用於攔截Executor接口的query方法,在攔截之后實現自己的query方法邏輯,之后可以選擇是否繼續執行原來的query方法。
對於攔截器Mybatis為我們提供了一個Interceptor接口,通過實現該接口就可以定義我們自己的攔截器。我們先來看一下這個接口的定義:

我們可以看到在該接口中一共定義有三個方法,intercept、plugin和setProperties。plugin方法是攔截器用於封裝目標對象的,通過該方法我們可以返回目標對象本身,也可以返回一個它的代理。當返回的是代理的時候我們可以對其中的方法進行攔截來調用intercept方法,當然也可以調用其他方法,這點將在后文講解。setProperties方法是用於在Mybatis配置文件中指定一些屬性的。
定義自己的Interceptor最重要的是要實現plugin方法和intercept方法,在plugin方法中我們可以決定是否要進行攔截進而決定要返回一個什么樣的目標對象。而intercept方法就是要進行攔截的時候要執行的方法。
對於plugin方法而言,其實Mybatis已經為我們提供了一個實現。Mybatis中有一個叫做Plugin的類,里面有一個靜態方法wrap(Object target,Interceptor interceptor),通過該方法可以決定要返回的對象是目標對象還是對應的代理。
對於實現自己的Interceptor而言有兩個很重要的注解,一個是@Intercepts,其值是一個@Signature數組。@Intercepts用於表明當前的對象是一個Interceptor,而@Signature則表明要攔截的接口、方法以及對應的參數類型。
創建自己的攔截器:MySimpleInterceptor.java
1 package com.chenyanbin.util; 2 3 import java.util.Properties; 4 5 import org.apache.ibatis.executor.Executor; 6 import org.apache.ibatis.mapping.MappedStatement; 7 import org.apache.ibatis.plugin.Interceptor; 8 import org.apache.ibatis.plugin.Intercepts; 9 import org.apache.ibatis.plugin.Invocation; 10 import org.apache.ibatis.plugin.Plugin; 11 import org.apache.ibatis.plugin.Signature; 12 import org.apache.ibatis.session.ResultHandler; 13 import org.apache.ibatis.session.RowBounds; 14 15 @Intercepts({ @Signature(method = "query", type = Executor.class, args = { MappedStatement.class, Object.class, 16 RowBounds.class, ResultHandler.class }) }) 17 public class MySimpleInterceptor implements Interceptor { 18 /* 19 * 參數:Invocation {代理對象,被監控的方法對象,當前被監控方法運行時需要實參} 20 */ 21 public Object intercept(Invocation invocation) throws Throwable { 22 // TODO Auto-generated method stub 23 System.out.println("被攔截方法執行之前,做的輔助服務。。。。。"); 24 Object object = invocation.proceed(); // 執行被攔截方法 25 System.out.println("被攔截方法執行之后,做的輔助服務。。。。。"); 26 return object; 27 } 28 29 /* 30 * 參數:target 表示被攔截的對象,應該是Executor接口實例對象 作用: 如果 被攔截的對象所在的類是有實現接口就為當前攔截對象生成一個代理對象 31 * 如果被攔截的對象所在的類沒有指定接口,這個對象之后的行為不會被代理操作 32 */ 33 public Object plugin(Object target) { 34 // TODO Auto-generated method stub 35 return Plugin.wrap(target, this); 36 } 37 38 public void setProperties(Properties properties) { 39 // TODO Auto-generated method stub 40 41 } 42 43 }
MyBatis核心配置文件:myBatis-config.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <configuration> 6 <!-- 屬性配置 --> 7 <properties resource="config.properties"></properties> 8 <!-- 別名配置 --> 9 <typeAliases> 10 <package name="com.chenyanbin.beans" /> 11 <package name="com.chenyanbin.dao" /> 12 </typeAliases> 13 <!-- ObjectFactory對象工廠 --> 14 <objectFactory type="com.chenyanbin.util.MyObjectFactory"></objectFactory> 15 <!-- Plugins攔截器 --> 16 <plugins> 17 <plugin interceptor="com.chenyanbin.util.MySimpleInterceptor"></plugin> 18 </plugins> 19 <!-- 類型處理器 --> 20 <!-- <typeHandlers> 從java中的Boolean轉jdbc中的NUMERIC <typeHandler handler="com.chenyanbin.util.MyTypeHandler" 21 javaType="Boolean" jdbcType="NUMERIC" /> </typeHandlers> --> 22 <!-- 環境配置 --> 23 <environments default="development"> 24 <!-- 環境配置 --> 25 <environment id="development"> 26 <!-- 事務管理器 --> 27 <transactionManager type="JDBC"></transactionManager> 28 <!-- 數據源 --> 29 <dataSource type="pooled"> 30 <property name="driver" value="${jdbc.driver}" /> 31 <property name="url" value="${jdbc.url}" /> 32 <property name="username" value="${jdbc.username}" /> 33 <property name="password" value="${jdbc.password}" /> 34 </dataSource> 35 </environment> 36 </environments> 37 <!-- 映射器 --> 38 <mappers> 39 <package name="com.chenyanbin.dao" /> 40 </mappers> 41 </configuration>
單元測試
1 package com.chenyanbin.test; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.List; 6 import org.apache.ibatis.io.Resources; 7 import org.apache.ibatis.plugin.Interceptor; 8 import org.apache.ibatis.session.SqlSession; 9 import org.apache.ibatis.session.SqlSessionFactory; 10 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 11 import org.junit.After; 12 import org.junit.Before; 13 import org.junit.Test; 14 import com.chenyanbin.beans.Dept; 15 import com.chenyanbin.dao.DeptMapper; 16 17 public class TestMain_01 { 18 private SqlSession session; 19 20 @Before 21 public void Start() { 22 try { 23 InputStream inputStream = Resources.getResourceAsStream("myBatis-config.xml"); 24 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); 25 session = factory.openSession(); 26 } catch (Exception e) { 27 e.printStackTrace(); 28 } 29 } 30 31 @After 32 public void end() { 33 if (session == null) { 34 session.close(); 35 } 36 } 37 38 @Test 39 public void test01() throws IOException { 40 Dept d2 = new Dept(); 41 d2.setDname("上海事業部"); 42 d2.setLoc("上海"); 43 d2.setFlag(false); 44 session.insert("deptSave", d2); 45 session.commit(); 46 session.close(); 47 } 48 49 @Test 50 public void test02() { 51 Interceptor ccInterceptor; 52 DeptMapper dao=session.getMapper(DeptMapper.class); 53 List<Dept> deptList=dao.deptFind(); 54 System.out.println("ok"); 55 } 56 57 }

1 ##define an appender named console 2 log4j.appender.console=org.apache.log4j.ConsoleAppender 3 #The Target value is System.out or System.err 4 log4j.appender.console.Target=System.out 5 #set the layout type of the apperder 6 log4j.appender.console.layout=org.apache.log4j.PatternLayout 7 #set the layout format pattern 8 log4j.appender.console.layout.ConversionPattern=[%-5p] %m%n 9 10 ##define a logger 11 log4j.rootLogger=debug,console
MyBatis自定義攔截器,可以攔截接口只有四種.
- Executor.class
- StatementHandler.class
- ParameterHandler.class
- ResultSetHandler.class
第二章 MyBatis框架Mapper配置文件詳解
2.1 參數(#{參數名})
#{}實現的是向prepareStatement中的預處理語句中設置參數值,sql語句中#{}表示一個占位符即?

使用#{參數名},將參數的內容添加到sql語句中指定位置.
如果當前sql語句中只有一個參數,此時參數名稱可以隨意定義
但是,如果當前sql語句有多個參數,此時參數名稱應該是與當前表關聯[實體類的屬性名]或則[Map集合關鍵字]

上述SQL語句在調用時,我們可以分別采用如下兩種方式輸入參數

使用#{}讀取實體類對象屬性內容

使用#{}讀取map集合中關鍵字的值
2.2 #{}和${}區別
在MyBatis中提供了兩種方式讀取參數的內容到SQL語句中,分別是
#{參數名} :實體類對象或則Map集合讀取內容
${參數名} :實體類對象或則Map集合讀取內容
為了能夠看到兩種方式的區別,需要看到MyBatis執行時輸送的SQL情況.因此
需要借助Log4J日志進行觀察
第一步: 加載Log4j日志工具包到項目

第二步:將Log4j配置文件添加到src/main/resources下

接下來,我們可以查看

輸出結果

從這里我們可以看出兩者的區別:
#{} : 采用預編譯方式,可以防止SQL注入
${}: 采用直接賦值方式,無法阻止SQL注入攻擊
在大多數情況下,我們都是采用#{}讀取參數內容.但是在一些特殊的情況下,我們還是需要使用${}讀取參數的.
比如 有兩張表,分別是emp_2017 和 emp_2018 .如果需要在查詢語句中動態指定表名,就只能使用${}
<select>
select * from emp_${year}
<select>
1 <select id="deptFind2" resultType="Dept"> 2 select * from ${value} 3 </select>
再比如.需要動態的指定查詢中的排序字段,此時也只能使用${}
<select>
select * from dept order by ${name}
</select>
簡單來說,在JDBC不支持使用占位符的地方,都可以使用${}
2.3 resultMap
MyBatis框架中是根據表中字段名到實體類定位同名屬性的.如果出現了實體類屬性名與表中字段名不一致的情況,則無法自動進行對應.此時可以使用resultMap來重新建立實體類與字段名之間對應關系.
<!-- property對應實體類的屬性名稱,column為數據庫結果集的列的名稱 -->

映射表沒有的字段
表結構

EmpMapper.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.chenyanbin.dao.EmpMapper"> 6 <resultMap type="Employee" id="empMap"> 7 <constructor> 8 <arg column="hireDate" javaType="java.util.Date" /> 9 </constructor> 10 </resultMap> 11 <select id="empFind" resultMap="empMap"> 12 select * from emp2 13 </select> 14 </mapper>
EmpMapper.java
1 package com.chenyanbin.dao; 2 3 import java.util.List; 4 5 public interface EmpMapper { 6 public List empFind(); 7 }
Employee.java
1 package com.chenyanbin.beans; 2 3 import java.text.SimpleDateFormat; 4 import java.util.Date; 5 6 public class Employee { 7 private Integer empNo; 8 private String ename; 9 private String job; 10 private Double sal; 11 private Date hireDate; 12 // 職員工作年限 13 private int workAge; 14 15 // 構造函數 16 public Employee(Date tempDate) { 17 this.hireDate = tempDate; 18 SimpleDateFormat sdf = new SimpleDateFormat("yyyy"); 19 this.workAge = Integer.valueOf(sdf.format(new Date())) - Integer.valueOf(sdf.format(tempDate)); 20 21 } 22 23 public int getWorkAge() { 24 return workAge; 25 } 26 27 public void setWorkAge(int workAge) { 28 this.workAge = workAge; 29 } 30 31 public Integer getEmpNo() { 32 return empNo; 33 } 34 35 public void setEmpNo(Integer empNo) { 36 this.empNo = empNo; 37 } 38 39 public String getEname() { 40 return ename; 41 } 42 43 public void setEname(String ename) { 44 this.ename = ename; 45 } 46 47 public String getJob() { 48 return job; 49 } 50 51 public void setJob(String job) { 52 this.job = job; 53 } 54 55 public Double getSal() { 56 return sal; 57 } 58 59 public void setSal(Double sal) { 60 this.sal = sal; 61 } 62 63 public Date getHireDate() { 64 return hireDate; 65 } 66 67 public void setHireDate(Date hireDate) { 68 this.hireDate = hireDate; 69 } 70 }
單元測試
1 package com.chenyanbin.test; 2 3 import java.io.InputStream; 4 import java.util.List; 5 import org.apache.ibatis.io.Resources; 6 import org.apache.ibatis.session.SqlSession; 7 import org.apache.ibatis.session.SqlSessionFactory; 8 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 9 import org.junit.After; 10 import org.junit.Before; 11 import org.junit.Test; 12 13 import com.chenyanbin.beans.Employee; 14 import com.chenyanbin.dao.DeptMapper; 15 import com.chenyanbin.dao.EmpMapper; 16 17 public class TestMain_01 { 18 private SqlSession session; 19 20 @Before 21 public void Start() { 22 try { 23 InputStream inputStream = Resources.getResourceAsStream("myBatis-config.xml"); 24 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); 25 session = factory.openSession(); 26 } catch (Exception e) { 27 e.printStackTrace(); 28 } 29 } 30 31 @After 32 public void end() { 33 if (session == null) { 34 session.close(); 35 } 36 } 37 @Test 38 public void test01() { 39 try { 40 EmpMapper dao=session.getMapper(EmpMapper.class); 41 List<Employee> deptList=dao.empFind(); 42 System.out.println("sssss"); 43 } catch (Exception e) { 44 e.printStackTrace(); 45 } 46 } 47 }
項目結構

2.4 Sql標簽
首先,我們如下兩條SQL映射

這兩條查詢映射中要查詢的表以及查詢的字段是完全一致的.因此可以<sql>標簽
將[select * from dept]進行抽取.

在需要使用到這個查詢的地方,通過<include>標簽進行引用

第三章 MyBatis動態SQL
3.1 什么是MyBatis動態SQL
根據用戶提供的參數,動態決定查詢語句依賴的查詢條件或則SQL語句的內容
3.2 動態SQL依賴標簽
- if
- choose、when、otherwise
- trim、where、set
- foreach
if使用

choose、when、otherwise
類似於Java中的switch case default. 只有一個條件生效,也就是只執行滿足的條件when,沒有滿足的條件就執行otherwise,表示默認條件

when的使用

set使用
會在成功拼接的條件前加上SET單詞且最后一個”,”號會被無視掉

trim使用

foreach的使用
foreach標簽用於對集合內容進行遍歷,將得到內容作為SQL語句的一部分.
在實際開發過程中主要用於in語句的構建和批量添加操作
foreach元素的屬性主要有 item,index,collection,open,separator,close。

案例1.使用foreach實現批處理添加

案例2.使用foreach遍歷list集合作為查詢條件

案例3.使用foreach遍歷數組作為查詢條件

案例4.使用foreach遍歷Map作為查詢條件

1 public List findForeachByMap(@Param("myMap")Map amp);
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.chenyanbin.dao.DeptMapper"> 6 <resultMap type="dept" id="deptMap"> 7 <id column="dept_deptno" property="deptNo" /> 8 <result column="dname" property="dname" /> 9 <result column="loc" property="loc" /> 10 <!-- collection標簽中,column屬性應該填寫查詢臨時表中來自一方表主鍵字段名 --> 11 <collection property="empList" ofType="Employee" 12 column="dept_deptno"> 13 <id column="empno" property="empNo" /> 14 <result column="ename" property="ename" /> 15 </collection> 16 </resultMap> 17 <!-- 查詢當前部門下所有的職員名稱以及當前部門基本信息 --> 18 <select id="deptFindById" resultMap="deptMap"> 19 select dept.deptno 20 dept_deptno,dept.dname,dept.loc,emp.empno,emp.ename,emp.sal from dept 21 join emp on dept.deptno=emp.deptno where dept.deptno=#{deptno} 22 </select> 23 </mapper> 24 25 ============================= 26 package com.chenyanbin.beans; 27 28 import java.util.List; 29 30 public class Dept { 31 private Integer deptNo; 32 private String dname; 33 private String loc; 34 //隸屬於當前部門下的所有職員集合 35 private List<Employee> empList; 36 public List<Employee> getEmpList() { 37 return empList; 38 } 39 public void setEmpList(List<Employee> empList) { 40 this.empList = empList; 41 } 42 public Integer getDeptNo() { 43 return deptNo; 44 } 45 public void setDeptNo(Integer deptNo) { 46 this.deptNo = deptNo; 47 } 48 public String getDname() { 49 return dname; 50 } 51 public void setDname(String dname) { 52 this.dname = dname; 53 } 54 public String getLoc() { 55 return loc; 56 } 57 public void setLoc(String loc) { 58 this.loc = loc; 59 } 60 } 61 62 63 ==================================== 64 package com.chenyanbin.beans; 65 66 import java.util.Date; 67 68 public class Employee { 69 private Integer empNo; 70 private String ename; 71 private String job; 72 private Double sal; 73 private Date hireDate; 74 // 職員工作年限 75 private int workAge; 76 77 78 public int getWorkAge() { 79 return workAge; 80 } 81 82 public void setWorkAge(int workAge) { 83 this.workAge = workAge; 84 } 85 86 public Integer getEmpNo() { 87 return empNo; 88 } 89 90 public void setEmpNo(Integer empNo) { 91 this.empNo = empNo; 92 } 93 94 public String getEname() { 95 return ename; 96 } 97 98 public void setEname(String ename) { 99 this.ename = ename; 100 } 101 102 public String getJob() { 103 return job; 104 } 105 106 public void setJob(String job) { 107 this.job = job; 108 } 109 110 public Double getSal() { 111 return sal; 112 } 113 114 public void setSal(Double sal) { 115 this.sal = sal; 116 } 117 118 public Date getHireDate() { 119 return hireDate; 120 } 121 122 public void setHireDate(Date hireDate) { 123 this.hireDate = hireDate; 124 } 125 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 <mapper namespace="com.chenyanbin.dao.DeptMapper"> 6 <resultMap type="dept" id="deptMap"> 7 <id column="dept_deptno" property="deptNo" /> 8 <result column="dname" property="dname" /> 9 <result column="loc" property="loc" /> 10 <!-- collection標簽中,column屬性應該填寫查詢臨時表中來自一方表主鍵字段名 --> 11 <collection property="empList" ofType="Employee" 12 select="empFindByDeptNo" column="dept_deptno"> 13 </collection> 14 </resultMap> 15 <!-- 根據部門編號查詢部門中的職員信息 --> 16 <select id="empFindByDeptNo" resultType="Employee"> 17 select empno,ename,job 18 from emp where deptno=#{deptno} 19 </select> 20 <!-- 根據部門編號查詢部門信息 --> 21 <select id="deptFindByDeptNo" resultMap="deptMap"> 22 select deptNo 23 dept_deptno,dname,loc from dept where deptno=#{deptno} 24 </select> 25 </mapper>
