mybatis 配置文件詳解

Mapper XML Files

mybatis 的映射文件重要性就不說了,除了使用了映射文件還有一種就是使用註解的方式,我們先看看優缺點:
在這裏插入圖片描述

既然支持2種形式現在我就思考2個問題?

這2種方式是否可以同時使用?

答案是肯定的可以使用

如果一個方法同時在xml配置也使用annotation註解哪個起作用?

答案是:不允許這樣做的,也好理解,不然mybatis不知道使用哪個實例化.

拋出的異常爲:

org.apache.ibatis.exceptions.PersistenceException: 
### Error building SqlSession.
### The error may exist in com/hrp/sys/dao/DemoMapper.java (best guess)
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for com.hrp.sys.dao.DemoMapper.getUser

	at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
	at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:80)
	at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:64)
	at test.TestMybatis.test(TestMybatis.java:41)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for com.hrp.sys.dao.DemoMapper.getUser
	at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:120)
	at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:98)
	at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:78)
	... 24 more
Caused by: java.lang.IllegalArgumentException: Mapped Statements collection already contains value for com.hrp.sys.dao.DemoMapper.getUser
	at org.apache.ibatis.session.Configuration$StrictMap.put(Configuration.java:844)
	at org.apache.ibatis.session.Configuration$StrictMap.put(Configuration.java:816)
	at org.apache.ibatis.session.Configuration.addMappedStatement(Configuration.java:640)
	at org.apache.ibatis.builder.MapperBuilderAssistant.addMappedStatement(MapperBuilderAssistant.java:302)
	at org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.parseStatement(MapperAnnotationBuilder.java:326)
	at org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.parse(MapperAnnotationBuilder.java:131)
	at org.apache.ibatis.binding.MapperRegistry.addMapper(MapperRegistry.java:72)
	at org.apache.ibatis.session.Configuration.addMapper(Configuration.java:713)
	at org.apache.ibatis.builder.xml.XMLMapperBuilder.bindMapperForNamespace(XMLMapperBuilder.java:408)
	at org.apache.ibatis.builder.xml.XMLMapperBuilder.parse(XMLMapperBuilder.java:94)
	at org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement(XMLConfigBuilder.java:368)
	at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:118)
	... 26 more

因爲我的項目中使用的映射文件這裏重點講解寫映射文件

映射文件中的標籤有多少?

The Mapper XML files have only a few first class elements (in the order that they should be defined):

  1. cache – Configuration of the cache for a given namespace.
  2. cache-ref – Reference to a cache configuration from another namespace.
  3. resultMap – The most complicated and powerful element that describes how to load your objects from the database result sets.
  4. parameterMap – Deprecated! Old-school way to map parameters. Inline parameters are preferred and this element may be removed in the future. Not documented here.
  5. sql – A reusable chunk of SQL that can be referenced by other statements.
  6. insert – A mapped INSERT statement.
  7. update – A mapped UPDATE statement.
  8. delete – A mapped DELETE statement.
  9. select – A mapped SELECT statement.

在這裏插入圖片描述

insert update delete

最基本的

接口
public void insert(SysUser sysUser);
mapper文件
  <insert id="insert" >
        insert into wfg (wfg_code, wfg_name)
        values (#{userCode}, #{userName})
    </insert>

/**
* 測試增刪改
* 1、mybatis允許增刪改直接定義以下類型返回值
* Integer、Long、Boolean、void
* 2、我們需要手動提交數據
* sqlSessionFactory.openSession();=》手動提交
* sqlSessionFactory.openSession(true);
=》自動提交
* @throws IOException
*/

<insert
  id="insertAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  keyProperty=""
  keyColumn=""
  useGeneratedKeys=""
  timeout="20">

<update
  id="updateAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">

<delete
  id="deleteAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">

獲取自增主鍵id

 parameterType 可以不寫
 獲取自增主鍵的值
  mybatis支持自增主鍵,通過statement.getGeneratedkeys()
  useGeneratedKeys 使用自增主鍵獲取策略
  keyProperty 就是獲取註解賦值給java bean 中的哪個屬性

參數處理

單個參數:mybatis不會做特殊處理,
#{參數名/任意名}:取出參數值。

多個參數:mybatis會做特殊處理。
多個參數會被封裝成 一個map,
key:param1…paramN,或者參數的索引也可以
value:傳入的參數值
#{}就是從map中獲取指定的key的值;

異常:
org.apache.ibatis.binding.BindingException: 
Parameter 'id' not found. 
Available parameters are [1, 0, param1, param2]
操作:
	方法:public Employee getEmpByIdAndLastName(Integer id,String lastName);
	取值:#{id},#{lastName}

【命名參數】:明確指定封裝參數時map的key;@Param(“id”)
多個參數會被封裝成 一個map,
key:使用@Param註解指定的值
value:參數值
#{指定的key}取出對應的參數值

POJO:
如果多個參數正好是我們業務邏輯的數據模型,我們就可以直接傳入pojo;
#{屬性名}:取出傳入的pojo的屬性值

Map:
如果多個參數不是業務模型中的數據,沒有對應的pojo,不經常使用,爲了方便,我們也可以傳入map
#{key}:取出map中對應的值

TO:
如果多個參數不是業務模型中的數據,但是經常要使用,推薦來編寫一個TO(Transfer Object)數據傳輸對象
Page{
int index;
int size;
}

思考========
public Employee getEmp(@Param(“id”)Integer id,String lastName);
取值:id==>#{id/param1} lastName==>#{param2}

public Employee getEmp(Integer id,@Param(“e”)Employee emp);
取值:id==>#{param1} lastName===>#{param2.lastName/e.lastName}

##特別注意:如果是Collection(List、Set)類型或者是數組,
也會特殊處理。也是把傳入的list或者數組封裝在map中。
key:Collection(collection),如果是List還可以使用這個key(list)
數組(array)
public Employee getEmpById(List ids);
取值:取出第一個id的值: #{list[0]}

結合源碼,mybatis怎麼處理參數==
總結:參數多時會封裝map,爲了不混亂,我們可以使用@Param來指定封裝時使用的key;
#{key}就可以取出map中的值;

(@Param(“id”)Integer id,@Param(“lastName”)String lastName);
ParamNameResolver解析參數封裝map的;
//1、names:{0=id, 1=lastName};構造器的時候就確定好了

確定流程:
1.獲取每個標了param註解的參數的@Param的值:id,lastName;  賦值給name;
2.每次解析一個參數給map中保存信息:(key:參數索引,value:name的值)
	name的值:
		標註了param註解:註解的值
		沒有標註:
			1.全局配置:useActualParamName(jdk1.8):name=參數名
			2.name=map.size();相當於當前元素的索引
{0=id, 1=lastName,2=2}

args【1,“Tom”,‘hello’】:

public Object getNamedParams(Object[] args) {
final int paramCount = names.size();
//1、參數爲null直接返回
if (args == null || paramCount == 0) {
return null;

//2、如果只有一個元素,並且沒有Param註解;args[0]:單個參數直接返回
} else if (!hasParamAnnotation && paramCount == 1) {
  return args[names.firstKey()];
  
//3、多個元素或者有Param標註
} else {
  final Map<String, Object> param = new ParamMap<Object>();
  int i = 0;
  
  //4、遍歷names集合;{0=id, 1=lastName,2=2}
  for (Map.Entry<Integer, String> entry : names.entrySet()) {
  
  	//names集合的value作爲key;  names集合的key又作爲取值的參考args[0]:args【1,"Tom"】:
  	//eg:{id=args[0]:1,lastName=args[1]:Tom,2=args[2]}
    param.put(entry.getValue(), args[entry.getKey()]);
    
    
    // add generic param names (param1, param2, ...)param
    //額外的將每一個參數也保存到map中,使用新的key:param1...paramN
    //效果:有Param註解可以#{指定的key},或者#{param1}
    final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
    // ensure not to overwrite parameter named with @Param
    if (!names.containsValue(genericParamName)) {
      param.put(genericParamName, args[entry.getKey()]);
    }
    i++;
  }
  return param;
}

}
}
=參數值的獲取============
#{}:可以獲取map中的值或者pojo對象屬性的值;
${}:可以獲取map中的值或者pojo對象屬性的值;

select * from tbl_employee where id=${id} and last_name=#{lastName}
Preparing: select * from tbl_employee where id=2 and last_name=?
區別:
#{}:是以預編譯的形式,將參數設置到sql語句中;PreparedStatement;防止sql注入
${}:取出的值直接拼裝在sql語句中;會有安全問題;
大多情況下,我們去參數的值都應該去使用#{};

	原生jdbc不支持佔位符的地方我們就可以使用${}進行取值
	比如分表、排序。。。;按照年份分表拆分
		select * from ${year}_salary where xxx;
		select * from tbl_employee order by ${f_name} ${order}

#{}:更豐富的用法:
規定參數的一些規則:
javaType、 jdbcType、 mode(存儲過程)、 numericScale、
resultMap、 typeHandler、 jdbcTypeName、 expression(未來準備支持的功能);

jdbcType通常需要在某種特定的條件下被設置:
	在我們數據爲null的時候,有些數據庫可能不能識別mybatis對null的默認處理。比如Oracle(報錯);
	
	JdbcType OTHER:無效的類型;因爲mybatis對所有的null都映射的是原生Jdbc的OTHER類型,oracle不能正確處理;
	
	由於全局配置中:jdbcTypeForNull=OTHER;oracle不支持;兩種辦法
	1、#{email,jdbcType=OTHER};
	2、jdbcTypeForNull=NULL
		<setting name="jdbcTypeForNull" value="NULL"/>

select 返回值

<select
  id="selectPerson"
  parameterType="int"
  parameterMap="deprecated"
  resultType="hashmap"
  resultMap="personResultMap"
  flushCache="false"
  useCache="true"
  timeout="10"
  fetchSize="256"
  statementType="PREPARED"
  resultSetType="FORWARD_ONLY">

返回類型 resultType

1.如果返回的是集合類型,我們寫的是集合元素的類型

  <select id="findAll" resultType="com.hrp.sys.entity.SysUser">
        select  user_code  , user_name as userName from sys_user ;

    </select>
  1. 返回類型是map
  2. 自定義resultMap
    自定義map包括多個級聯查詢,一對多查一的方時加載多方, 查詢多方時加載一方時,懶加載等方式 參考下面的實例
    內容有些多 後期使用的時候 自己再消化下吧

DepartmentMapper

<?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.atguigu.mybatis.dao.DepartmentMapper">
	<!--public Department getDeptById(Integer id);  -->
	<select id="getDeptById" resultType="com.atguigu.mybatis.bean.Department">
		select id,dept_name departmentName from tbl_dept where id=#{id}
	</select>
	
	
	
	<!-- 
	public class Department {
			private Integer id;
			private String departmentName;
			private List<Employee> emps;
	  did  dept_name  ||  eid  last_name  email   gender  
	 -->
	 
	<!--嵌套結果集的方式,使用collection標籤定義關聯的集合類型的屬性封裝規則  -->
	<resultMap type="com.atguigu.mybatis.bean.Department" id="MyDept">
		<id column="did" property="id"/>
		<result column="dept_name" property="departmentName"/>
		<!-- 
			collection定義關聯集合類型的屬性的封裝規則 
			ofType:指定集合裏面元素的類型
		-->
		<collection property="emps" ofType="com.atguigu.mybatis.bean.Employee">
			<!-- 定義這個集合中元素的封裝規則 -->
			<id column="eid" property="id"/>
			<result column="last_name" property="lastName"/>
			<result column="email" property="email"/>
			<result column="gender" property="gender"/>
		</collection>
	</resultMap>
	<!-- public Department getDeptByIdPlus(Integer id); -->
	<select id="getDeptByIdPlus" resultMap="MyDept">
		SELECT d.id did,d.dept_name dept_name,
				e.id eid,e.last_name last_name,e.email email,e.gender gender
		FROM tbl_dept d
		LEFT JOIN tbl_employee e
		ON d.id=e.d_id
		WHERE d.id=#{id}
	</select>
	
	<!-- collection:分段查詢 -->
	<resultMap type="com.atguigu.mybatis.bean.Department" id="MyDeptStep">
		<id column="id" property="id"/>
		<id column="dept_name" property="departmentName"/>
		<collection property="emps" 
			select="com.atguigu.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId"
			column="{deptId=id}" fetchType="lazy"></collection>
	</resultMap>
	<!-- public Department getDeptByIdStep(Integer id); -->
	<select id="getDeptByIdStep" resultMap="MyDeptStep">
		select id,dept_name from tbl_dept where id=#{id}
	</select>
	
	<!-- 擴展:多列的值傳遞過去:
			將多列的值封裝map傳遞;
			column="{key1=column1,key2=column2}"
		fetchType="lazy":表示使用延遲加載;
				- lazy:延遲
				- eager:立即
	 -->
</mapper>

EmployeeMapper

<?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.atguigu.mybatis.dao.EmployeeMapper">
<!-- 
namespace:名稱空間;指定爲接口的全類名
id:唯一標識
resultType:返回值類型
#{id}:從傳遞過來的參數中取出id值
public Employee getEmpById(Integer id);
 -->
 
 	<!--public Map<Integer, Employee> getEmpByLastNameLikeReturnMap(String lastName);  -->
 	<select id="getEmpByLastNameLikeReturnMap" resultType="com.atguigu.mybatis.bean.Employee">
 		select * from tbl_employee where last_name like #{lastName}
 	</select>
 
 	<!--public Map<String, Object> getEmpByIdReturnMap(Integer id);  -->
 	<select id="getEmpByIdReturnMap" resultType="map">
 		select * from tbl_employee where id=#{id}
 	</select>
 
	<!-- public List<Employee> getEmpsByLastNameLike(String lastName); -->
	<!--resultType:如果返回的是一個集合,要寫集合中元素的類型  -->
	<select id="getEmpsByLastNameLike" resultType="com.atguigu.mybatis.bean.Employee">
		select * from tbl_employee where last_name like #{lastName}
	</select>

 	<!-- public Employee getEmpByMap(Map<String, Object> map); -->
 	<select id="getEmpByMap" resultType="com.atguigu.mybatis.bean.Employee">
 		select * from ${tableName} where id=${id} and last_name=#{lastName}
 	</select>
 
 	<!--  public Employee getEmpByIdAndLastName(Integer id,String lastName);-->
 	<select id="getEmpByIdAndLastName" resultType="com.atguigu.mybatis.bean.Employee">
 		select * from tbl_employee where id = #{id} and last_name=#{lastName}
 	</select>
 	
 	<select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee">
		select * from tbl_employee where id = #{id}
	</select>
	<select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee"
		databaseId="mysql">
		select * from tbl_employee where id = #{id}
	</select>
	<select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee"
		databaseId="oracle">
		select EMPLOYEE_ID id,LAST_NAME	lastName,EMAIL email 
		from employees where EMPLOYEE_ID=#{id}
	</select>
	
	<!-- public void addEmp(Employee employee); -->
	<!-- parameterType:參數類型,可以省略, 
	獲取自增主鍵的值:
		mysql支持自增主鍵,自增主鍵值的獲取,mybatis也是利用statement.getGenreatedKeys();
		useGeneratedKeys="true";使用自增主鍵獲取主鍵值策略
		keyProperty;指定對應的主鍵屬性,也就是mybatis獲取到主鍵值以後,將這個值封裝給javaBean的哪個屬性
	-->
	<insert id="addEmp" parameterType="com.atguigu.mybatis.bean.Employee"
		useGeneratedKeys="true" keyProperty="id" databaseId="mysql">
		insert into tbl_employee(last_name,email,gender) 
		values(#{lastName},#{email},#{gender})
	</insert>
	
	<!-- 
	獲取非自增主鍵的值:
		Oracle不支持自增;Oracle使用序列來模擬自增;
		每次插入的數據的主鍵是從序列中拿到的值;如何獲取到這個值;
	 -->
	<insert id="addEmp" databaseId="oracle">
		<!-- 
		keyProperty:查出的主鍵值封裝給javaBean的哪個屬性
		order="BEFORE":當前sql在插入sql之前運行
			   AFTER:當前sql在插入sql之後運行
		resultType:查出的數據的返回值類型
		
		BEFORE運行順序:
			先運行selectKey查詢id的sql;查出id值封裝給javaBean的id屬性
			在運行插入的sql;就可以取出id屬性對應的值
		AFTER運行順序:
			先運行插入的sql(從序列中取出新值作爲id);
			再運行selectKey查詢id的sql;
		 -->
		<selectKey keyProperty="id" order="BEFORE" resultType="Integer">
			<!-- 編寫查詢主鍵的sql語句 -->
			<!-- BEFORE-->
			select EMPLOYEES_SEQ.nextval from dual 
			<!-- AFTER:
			 select EMPLOYEES_SEQ.currval from dual -->
		</selectKey>
		
		<!-- 插入時的主鍵是從序列中拿到的 -->
		<!-- BEFORE:-->
		insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) 
		values(#{id},#{lastName},#{email<!-- ,jdbcType=NULL -->}) 
		<!-- AFTER:
		insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) 
		values(employees_seq.nextval,#{lastName},#{email}) -->
	</insert>
	
	<!-- public void updateEmp(Employee employee);  -->
	<update id="updateEmp">
		update tbl_employee 
		set last_name=#{lastName},email=#{email},gender=#{gender}
		where id=#{id}
	</update>
	
	<!-- public void deleteEmpById(Integer id); -->
	<delete id="deleteEmpById">
		delete from tbl_employee where id=#{id}
	</delete>
	
	
</mapper>

EmployeeMapperPlus

<?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.atguigu.mybatis.dao.EmployeeMapperPlus">

	<!--自定義某個javaBean的封裝規則
	type:自定義規則的Java類型
	id:唯一id方便引用
	  -->
	<resultMap type="com.atguigu.mybatis.bean.Employee" id="MySimpleEmp">
		<!--指定主鍵列的封裝規則
		id定義主鍵會底層有優化;
		column:指定哪一列
		property:指定對應的javaBean屬性
		  -->
		<id column="id" property="id"/>
		<!-- 定義普通列封裝規則 -->
		<result column="last_name" property="lastName"/>
		<!-- 其他不指定的列會自動封裝:我們只要寫resultMap就把全部的映射規則都寫上。 -->
		<result column="email" property="email"/>
		<result column="gender" property="gender"/>
	</resultMap>
	
	<!-- resultMap:自定義結果集映射規則;  -->
	<!-- public Employee getEmpById(Integer id); -->
	<select id="getEmpById"  resultMap="MySimpleEmp">
		select * from tbl_employee where id=#{id}
	</select>
	
	<!-- 
	場景一:
		查詢Employee的同時查詢員工對應的部門
		Employee===Department
		一個員工有與之對應的部門信息;
		id  last_name  gender    d_id     did  dept_name (private Department dept;)
	 -->
	 
	 
	<!--
		聯合查詢:級聯屬性封裝結果集
	  -->
	<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp">
		<id column="id" property="id"/>
		<result column="last_name" property="lastName"/>
		<result column="gender" property="gender"/>
		<result column="did" property="dept.id"/>
		<result column="dept_name" property="dept.departmentName"/>
	</resultMap>


	<!-- 
		使用association定義關聯的單個對象的封裝規則;
	 -->
	<resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp2">
		<id column="id" property="id"/>
		<result column="last_name" property="lastName"/>
		<result column="gender" property="gender"/>
		
		<!--  association可以指定聯合的javaBean對象
		property="dept":指定哪個屬性是聯合的對象
		javaType:指定這個屬性對象的類型[不能省略]
		-->
		<association property="dept" javaType="com.atguigu.mybatis.bean.Department">
			<id column="did" property="id"/>
			<result column="dept_name" property="departmentName"/>
		</association>
	</resultMap>
	<!--  public Employee getEmpAndDept(Integer id);-->
	<select id="getEmpAndDept" resultMap="MyDifEmp">
		SELECT e.id id,e.last_name last_name,e.gender gender,e.d_id d_id,
		d.id did,d.dept_name dept_name FROM tbl_employee e,tbl_dept d
		WHERE e.d_id=d.id AND e.id=#{id}
	</select>
	
	<!-- 使用association進行分步查詢:
		1、先按照員工id查詢員工信息
		2、根據查詢員工信息中的d_id值去部門表查出部門信息
		3、部門設置到員工中;
	 -->
	 
	 <!--  id  last_name  email   gender    d_id   -->
	 <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpByStep">
	 	<id column="id" property="id"/>
	 	<result column="last_name" property="lastName"/>
	 	<result column="email" property="email"/>
	 	<result column="gender" property="gender"/>
	 	<!-- association定義關聯對象的封裝規則
	 		select:表明當前屬性是調用select指定的方法查出的結果
	 		column:指定將哪一列的值傳給這個方法
	 		
	 		流程:使用select指定的方法(傳入column指定的這列參數的值)查出對象,並封裝給property指定的屬性
	 	 -->
 		<association property="dept" 
	 		select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById"
	 		column="d_id">
 		</association>
	 </resultMap>
	 <!--  public Employee getEmpByIdStep(Integer id);-->
	 <select id="getEmpByIdStep" resultMap="MyEmpByStep">
	 	select * from tbl_employee where id=#{id}
	 	<if test="_parameter!=null">
	 		and 1=1
	 	</if>
	 </select>
	 
	 <!-- 可以使用延遲加載(懶加載);(按需加載)
	 	Employee==>Dept:
	 		我們每次查詢Employee對象的時候,都將一起查詢出來。
	 		部門信息在我們使用的時候再去查詢;
	 		分段查詢的基礎之上加上兩個配置:
	  -->
	<!-- ==================association============================ -->
	
	<!-- 
	場景二:
		查詢部門的時候將部門對應的所有員工信息也查詢出來:註釋在DepartmentMapper.xml中
	 -->
	<!-- public List<Employee> getEmpsByDeptId(Integer deptId); -->
	<select id="getEmpsByDeptId" resultType="com.atguigu.mybatis.bean.Employee">
		select * from tbl_employee where d_id=#{deptId}
	</select>
	
	
	
	<!-- =======================鑑別器============================ -->
	<!-- <discriminator javaType=""></discriminator>
		鑑別器:mybatis可以使用discriminator判斷某列的值,然後根據某列的值改變封裝行爲
		封裝Employee:
			如果查出的是女生:就把部門信息查詢出來,否則不查詢;
			如果是男生,把last_name這一列的值賦值給email;
	 -->
	 <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpDis">
	 	<id column="id" property="id"/>
	 	<result column="last_name" property="lastName"/>
	 	<result column="email" property="email"/>
	 	<result column="gender" property="gender"/>
	 	<!--
	 		column:指定判定的列名
	 		javaType:列值對應的java類型  -->
	 	<discriminator javaType="string" column="gender">
	 		<!--女生  resultType:指定封裝的結果類型;不能缺少。/resultMap-->
	 		<case value="0" resultType="com.atguigu.mybatis.bean.Employee">
	 			<association property="dept" 
			 		select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById"
			 		column="d_id">
		 		</association>
	 		</case>
	 		<!--男生 ;如果是男生,把last_name這一列的值賦值給email; -->
	 		<case value="1" resultType="com.atguigu.mybatis.bean.Employee">
		 		<id column="id" property="id"/>
			 	<result column="last_name" property="lastName"/>
			 	<result column="last_name" property="email"/>
			 	<result column="gender" property="gender"/>
	 		</case>
	 	</discriminator>
	 </resultMap>
</mapper>

sql

sql 複用

This element can be used to define a reusable fragment of SQL code that can be included in other statements. It can be statically (during load phase) parametrized. Different property values can vary in include instances. For example:

<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>

The SQL fragment can then be included in another statement, for example:

<select id="selectUsers" resultType="map">
  select
    <include refid="userColumns"><property name="alias" value="t1"/></include>,
    <include refid="userColumns"><property name="alias" value="t2"/></include>
  from some_table t1
    cross join some_table t2
</select>

Property value can be also used in include refid attribute or property values inside include clause, for example:

<sql id="sometable">
  ${prefix}Table
</sql>

<sql id="someinclude">
  from
    <include refid="${include_target}"/>
</sql>

<select id="select" resultType="map">
  select
    field1, field2, field3
  <include refid="someinclude">
    <property name="prefix" value="Some"/>
    <property name="include_target" value="sometable"/>
  </include>
</select>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章