mybatis动态sql-(7)-内置参数和绑定

1、编辑接口文件方法

//内置参数
public List<Employee> getEmpsTestInnerParameter(Employee employee);

2、编辑全局配置文件,设置databaseId

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

	<settings>
		<setting name="mapUnderscoreToCamelCase" value="true" />
	</settings>

	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
				<property name="username" value="root" />
				<property name="password" value="Cool123!" />
			</dataSource>
		</environment>
	</environments>

	<databaseIdProvider type="DB_VENDOR">
		<!-- 为不同的数据库厂商起别名 -->
		<property name="MySQL" value="mysql" />
		<property name="Oracle" value="oracle" />
		<property name="SQL Server" value="sqlserver" />
	</databaseIdProvider>


	<!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 
		如果 数据库全局文件 和 子配置文件 不在同一个目录 ,就需要 /目录/目录/.../EmployeeMapper_old.xml -->
	<mappers>

		<!-- 新方法操作mybatis 需要 的配置文件 -->
		<mapper resource="EmployeeMapperDynamicSQL.xml" />
	</mappers>
</configuration>

3、编辑SQL映射文件

<!-- 两个内置参数:
	 不只是方法传递过来的参数可以被用来判断,取值。。。
	 mybatis默认还有两个内置参数:
	 _parameter:代表整个参数
	 	单个参数:_parameter就是这个参数
	 	多个参数:参数会被封装为一个map;_parameter就是代表这个map
	 	
	 _databaseId:如果配置了databaseIdProvider标签。
	 	_databaseId就是代表当前数据库的别名oracle
-->
	  
<!--public List<Employee> getEmpsTestInnerParameter(Employee employee);  -->
 <select id="getEmpsTestInnerParameter" resultType="com.mybatis.bean.Employee">
	  	<!-- bind:可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值 -->
	  	<bind name="_lastName" value="'%'+lastName+'%'"/>
	  	<if test="_databaseId=='mysql'">
	  		select * from tbl_employee
	  		<if test="_parameter!=null">
	  			where last_name like #{_lastName}
	  		</if>
	  	</if>
	  	<if test="_databaseId=='oracle'">
	  		select * from employees
	  		<if test="_parameter!=null">
	  			where last_name like #{_parameter.lastName}
	  		</if>
	  	</if>
 </select>

一般情况下:绑定不怎么用如  where last_name like #{_lastName}  _lastName是绑定,但是写在代码中,可以更方便的修改 模糊查询。

<bind name="_lastName" value="'%'+lastName+'%'"/>
	  <if test="_databaseId=='mysql'">
	  	select * from tbl_employee
	  	<if test="_parameter!=null">
	  		where last_name like #{_lastName}
	  	</if>
	  </if>

4、编辑Junit测试文件

@Test
public void testInnerParam() throws IOException{
	SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
	SqlSession openSession = sqlSessionFactory.openSession();
	try{
		EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class);
		Employee employee2 = new Employee();
		employee2.setLastName("e");
		List<Employee> list = mapper.getEmpsTestInnerParameter(employee2);
		for (Employee employee : list) {
			System.out.println(employee);
		}
	}finally{
		openSession.close();
	}
}

 

mybatis动态sql-(6)-批量插入foreach与sql片段抽取

mysql批量插入与oracle批量插入不同

一、搭建数据库

tbl_employee表【d_id 是外键 对应 tbl_dept表】

id	last_name    gender	  email       d_id
1	   mike	       0      [email protected]      1
2          book        0      [email protected]    2
3          tom         1      [email protected]    2
4          jerry       1       [email protected]       1

tbl_dept表:

id    dept_name
1      开发部
2      测试部

二、编辑javabean

package com.mybatis.bean;

public class Employee {
	private Integer id;
	private String lastName;
	private String email;
	private String gender;
	private Department department;

	
	public Department getDepartment() {
		return department;
	}

	public void setDepartment(Department department) {
		this.department = department;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	@Override
	public String toString() {
		return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + "]";
	}
	
   /*****  关键是 这个地方啊 出了 问题 ****/
	public Employee() {
		super();
	}
	/*****/
	public Employee(Integer id,String lastName, String  email, String gender){
		this.id =id;
		this.lastName =lastName;
		this.email =email;
		this.gender =gender;
		
	}
	
	public Employee(Integer id,String lastName, String  email, String gender,Department dep){
		this.id =id;
		this.lastName =lastName;
		this.email =email;
		this.gender =gender;
		this.department =dep;
	}
	
//  历史教训 ,一开始 没有添加 无参构造函数,而添加了下面这个函数	
//	public Employee(Integer id,String lastName, String  email, String gender,int temp){
//		this.id =id;
//		this.lastName =lastName;
//		this.email =email;
//		this.gender =gender;
//		
//		System.out.println(" id:"+id+" lastName:"+lastName+" email:"+email+" gender:"+gender+" temp:"+temp);
//	}

}
package com.mybatis.bean;

import java.util.List;

public class Department {

	private Integer id;
	private String departmentName;
	private List<Employee> employees;

	public Department() {
		
	}
	
    public Department(int id){
    	this.id = id;
		
	}

	public List<Employee> getEmployees() {
		return employees;
	}

	public void setEmployees(List<Employee> employees) {
		this.employees = employees;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getDepartmentName() {
		return departmentName;
	}

	public void setDepartmentName(String departmentName) {
		this.departmentName = departmentName;
	}

	@Override
	public String toString() {
		return "Department [id=" + id + ", departmentName=" + departmentName + "]";
	}

}

 

三、编辑junit测试

@Test
public void testBatchSave() throws IOException{
	SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
	SqlSession openSession = sqlSessionFactory.openSession();
	try{
		EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class);
		List<Employee> emps = new ArrayList<>();
		emps.add(new Employee(null, "smith0x1", "[email protected]", "1" , new Department(1) ));
		emps.add(new Employee(null, "allen0x1", "[email protected]", "0" , new Department(1) ));
		mapper.addEmps(emps);
		openSession.commit();
	}finally{
		openSession.close();
	}
}

四、编辑SQl映射文件

1、mysql 版

 <!--MySQL下批量保存:可以foreach遍历   mysql支持values(),(),()语法-->
<!-- 批量保存 -->
 <!--public void addEmps(@Param("emps")List<Employee> emps);  -->
 <!--MySQL下批量保存:可以foreach遍历   mysql支持values(),(),()语法-->
<insert id="addEmps">
	 insert into tbl_employee(last_name,email,gender,d_id) 
	values
	<foreach collection="emps" item="emp" separator=",">
		(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.department.id})
	</foreach>
 </insert><!--   -->
	 
 <!-- 这种方式需要数据库连接属性allowMultiQueries=true;
	 这种分号分隔多个sql可以用于其他的批量操作(删除,修改) -->
 <!-- <insert id="addEmps">
	 <foreach collection="emps" item="emp" separator=";">
	 	insert into tbl_employee(last_name,email,gender,d_id)
	 	values(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.department.id})
	 </foreach>
 </insert> -->

mysql补充:在mysql配置时,我们可能需要配置 allowMultiQueries=true
jdbc.url=jdbc:mysql://localhost:3306/mybatis?allowMultiQueries=true

若一个sql中通过分号分割(或包含)了多个独立sql的话,如:
select 'hello';select 'world'
就会报如下错:
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select 'world'' at line 1
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)

当若显式设置allowMultiQueries为true的话,就可以正常执行不会报错.如下所示:
String url = "jdbc:mysql://localhost:3306?allowMultiQueries=true";

官方文档解释:
allowMultiQueries
Allow the use of ';' to delimit multiple queries during one statement (true/false), defaults to 'false', and does not affect the addBatch() and executeBatch() methods, which instead rely on rewriteBatchStatements.
Default: false
Since version: 3.1.1

2、oracle版

 <!-- Oracle数据库批量保存: 
	 Oracle不支持values(),(),()
	 Oracle支持的批量方式
	 1、多个insert放在begin - end里面
	 	begin
		     insert into employees(employee_id,last_name,email) 
		     values(employees_seq.nextval,'test_001','[email protected]');
		     insert into employees(employee_id,last_name,email) 
		     values(employees_seq.nextval,'test_002','[email protected]');
		end;
	2、利用中间表:
		insert into employees(employee_id,last_name,email)
		   select employees_seq.nextval,lastName,email from(
		          select 'test_a_01' lastName,'test_a_e01' email from dual
		          union
		          select 'test_a_02' lastName,'test_a_e02' email from dual
		          union
		          select 'test_a_03' lastName,'test_a_e03' email from dual
		   )	
	 -->

实际写法:

<insert id="addEmps" databaseId="oracle">
	 <!-- oracle第一种批量方式 -->
	 <!-- <foreach collection="emps" item="emp" open="begin" close="end;">
	 	insert into employees(employee_id,last_name,email) 
		      values(employees_seq.nextval,#{emp.lastName},#{emp.email});
	 </foreach> -->
	 	
	 <!-- oracle第二种批量方式  -->
	 insert into employees(
	 	<!-- 引用外部定义的sql -->
	 	<include refid="insertColumn">
	 		<property name="testColomn" value="abc"/>
	 	</include>
	 )
	 		<foreach collection="emps" item="emp" separator="union"
	 			open="select employees_seq.nextval,lastName,email from("
	 			close=")">
	 			select #{emp.lastName} lastName,#{emp.email} email from dual
	 		</foreach>
 </insert>

特别提醒一下:下面的引用其实就是 待插入的 各个字段啦。

<!-- 引用外部定义的sql -->
	 <include refid="insertColumn">
	 	<property name="testColomn" value="abc"/>
	 </include>

用法说明:不是只能用在批量插入中,也可以用在其他数据操作中,因为只是对SQL片段的抽取。

 <!-- 
	  抽取可重用的sql片段。方便后面引用 
	  1、sql抽取:经常将要查询的列名,或者插入用的列名抽取出来方便引用
	  2、include来引用已经抽取的sql:
	  3、include还可以自定义一些property,sql标签内部就能使用自定义的属性
	  		include-property:取值的正确方式${prop},
	  		#{不能使用这种方式}
          4、employee_id,last_name,email,${prop} 这个oracle插入 其实等价于【当然数据库有没有相应字段是另一回事,在这里只是用来演示】 employee_id,last_name,email,abc
          5、_databaseId 是 mybatis 内置参数,和在 全局配置文件中,标记的数据库 名是 一样的
-->
  <sql id="insertColumn">
	  	<if test="_databaseId=='oracle'">
	  		employee_id,last_name,email,${prop}
	  	</if>
	  	<if test="_databaseId=='mysql'">
	  		last_name,email,gender,d_id
	  	</if>
 </sql>

 

mybatis动态sql-(5)-遍历查询foreach

一、编写接口方法:

package com.mybatis.mapper;

import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.mybatis.bean.Employee;

public interface EmployeeMapperDynamicSQL {
	
	//查询员工id'在给定集合中的
	public List<Employee> getEmpsByConditionForeach(@Param("ids")List<Integer> ids);

}

 二、编写sql映射文件

<?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.mybatis.mapper.EmployeeMapperDynamicSQL">

<!--public List<Employee> getEmpsByConditionForeach(List<Integer> ids);  -->
<select id="getEmpsByConditionForeach" resultType="com.mybatis.bean.Employee">
	 select * from tbl_employee
	 <!--
	 测试用例:
	 select * from tbl_employee where id in (1,2,3)
	 	
	 	collection:指定要遍历的集合:
	 		list类型的参数会特殊处理封装在map中,map的key就叫list
	 	item:将当前遍历出的元素赋值给指定的变量
	 	separator:每个元素之间的分隔符
	 	open:遍历出所有结果拼接一个开始的字符
	 	close:遍历出所有结果拼接一个结束的字符
	 	index:索引。遍历list的时候是index就是索引,item就是当前值
	 		   遍历map的时候index表示的就是map的key,item就是map的值
	 		
	 	#{变量名}就能取出变量的值也就是当前遍历出的元素
	  -->
	 <foreach collection="ids" item="item_id" separator=","
	 	open="where id in(" close=")">
	 	#{item_id}
	 </foreach>
</select>

</mapper>

 三、编写Junit测试

List<Employee> list = mapper.getEmpsByConditionForeach(Arrays.asList(1,2));
     for (Employee emp : list) {
	 System.out.println(emp);
}

 

mybatis动态sql-(4)-多次条件判断set和trim

当更新数据时,可以用 set 标签 来,来取消 更新语句中 多余的,
last_name=#{lastName}, 
比如上面这句话,如果是最后一个判断子句,那末尾的[,]是要去掉的,所以就需要用set标签了。trim标签之前提到过,功能很多,可以去头和去尾,也可以添加整句头和添加整句尾。

<!--public void updateEmp(Employee employee);  -->
<update id="updateEmp">
	 <!-- Set标签的使用 -->
	 update tbl_employee 
	<set>
		<if test="lastName!=null">
			last_name=#{lastName},
		</if>
		<if test="email!=null">
			email=#{email},
		</if>
		<if test="gender!=null">
			gender=#{gender}
		</if>
	</set>
	where id=#{id} 
<!-- 		
	Trim:更新拼串
	update tbl_employee 
	<trim prefix="set" suffixOverrides=",">
		<if test="lastName!=null">
			last_name=#{lastName},
		</if>
		<if test="email!=null">
			email=#{email},
		</if>
		<if test="gender!=null">
			gender=#{gender}
		</if>
	</trim>
	where id=#{id}  -->
 </update>

 

mybatis动态sql-(3)-单次条件判断choose

单次判断,就是只进行一次判断。

一、编辑接口文件

import java.util.List;
import org.apache.ibatis.annotations.Param;
import com.mybatis.bean.Employee;

public interface EmployeeMapperDynamicSQL {

       public List<Employee> getEmpsByConditionChoose(Employee employee);

}

二、编辑SQL映射文件

 <!-- public List<Employee> getEmpsByConditionChoose(Employee employee); -->
 <select id="getEmpsByConditionChoose" resultType="com.mybatis.bean.Employee">
	 select * from tbl_employee 
	 <where>
	 	<!-- 如果带了id就用id查,如果带了lastName就用lastName查;只会进入其中一个 -->
	 	<choose>
	 		<when test="id!=null">
	 			id=#{id}
	 		</when>
	 		<when test="lastName!=null">
	 			last_name like #{lastName}
	 		</when>
	 		<when test="email!=null">
	 			email = #{email}
	 		</when>
	 		<otherwise>
	 			gender = 0
	 		</otherwise>
	 	</choose>
	 </where>
 </select>

三、Junit单元测试

EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class);
Employee employee = new Employee(3,"%m%","[email protected]","2");

List<Employee> list = mapper.getEmpsByConditionChoose(employee);
	for(Employee emp :list){
	System.out.println(emp);
	System.out.println(emp.getDepartment());
}

 

mybatis动态sql-(2)-多次条件判断where和trim

在前面一中:

sql映射文件:只用到了if,如果 条件一 id 是null;

那么sql 语句 就成了select * from tbl_employee  where  and  id=#{id}   会报错

<select id="getEmpsByConditionIf" resultType="com.mybatis.bean.Employee">
	 	select * from tbl_employee where
	 	
		 	<!-- test:判断表达式(OGNL)
		 	OGNL参照PPT或者官方文档。
		 	  	 c:if  test
		 	从参数中取值进行判断
		 	
		 	遇见特殊符号应该去写转义字符:
		 	&&:
		 	-->
		 	<if test="id!=null">
		 		id=#{id}
		 	</if>
		 	<if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
		 		and last_name like #{lastName}
		 	</if>
		 	<if test="email!=null and email.trim()!=&quot;&quot;">
		 		and email=#{email}
		 	</if> 
		 	<!-- ognl会进行字符串与数字的转换判断  "0"==0 -->
		 	<if test="gender==0 or gender==1">
		 	 	and gender=#{gender}
		 	</if>
	 	
	 </select>


</mapper>

查询的时候如果某些条件没带可能sql拼装会有问题。

一、SQL条件语句问题简单解决方法

1、将SQL语句写成select * from tbl_employee  where  1=1
后面的条件语句都写成: and xxx 之类的。
2、mybatis使用where标签来将所有的查询条件包括在内。mybatis就会将where标签中拼装的sql,多出来的and或者or去掉where只会去掉第一个多出来的and或者or。

<?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.mybatis.mapper.EmployeeMapperDynamicSQL">
<!-- 
上面的 namespace:名称空间;指定为接口的全类名
下面的 id:唯一标识被规定为接口方法名 【public Employee getEmpById(Integer id);】
下面的 resultType:返回值类型
下面的 #{id}:从传递过来的参数中取出id值
 -->
	
<!-- 
• if:判断
• choose (when, otherwise):分支选择;带了break的swtich-case
	如果带了id就用id查,如果带了lastName就用lastName查;只会进入其中一个
• trim 字符串截取(where(封装查询条件), set(封装修改条件))
• foreach 遍历集合
	 -->
	 <!-- 查询员工,要求,携带了哪个字段查询条件就带上这个字段的值 -->
	 <!-- public List<Employee> getEmpsByConditionIf(Employee employee); -->
<select id="getEmpsByConditionIf" resultType="com.mybatis.bean.Employee">
	 	select * from tbl_employee
	 	
	 	<!-- where -->
	 	<where>
		 	<!-- test:判断表达式(OGNL)
		 	OGNL参照PPT或者官方文档。
		 	  	 c:if  test
		 	从参数中取值进行判断
		 	
		 	遇见特殊符号应该去写转义字符:
		 	&&:
		 	-->
		 	<if test="id!=null">
		 		id=#{id}
		 	</if>
		 	<if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
		 		and last_name like #{lastName}
		 	</if>
		 	<if test="email!=null and email.trim()!=&quot;&quot;">
		 		and email=#{email}
		 	</if> 
		 	<!-- ognl会进行字符串与数字的转换判断  "0"==0 -->
		 	<if test="gender==0 or gender==1">
		 	 	and gender=#{gender}
		 	</if>
	 	</where>
	 </select>


</mapper>

二、SQL条件语句问题高级解决方法

采用 trim 字符串截取方法:

<!--public List<Employee> getEmpsByConditionTrim(Employee employee);  -->
 <select id="getEmpsByConditionIf" resultType="com.atguigu.mybatis.bean.Employee">
	 select * from tbl_employee
	 <!-- 后面多出的and或者or where标签不能解决 
	 prefix="":前缀:trim标签体中是整个字符串拼串 后的结果。
	 		prefix给拼串后的整个字符串加一个前缀 
	 prefixOverrides="":
	 		前缀覆盖: 去掉整个字符串前面多余的字符
	 suffix="":后缀
	 		suffix给拼串后的整个字符串加一个后缀 
	 suffixOverrides=""
	 		后缀覆盖:去掉整个字符串后面多余的字符
	 			
	 -->
	 <!-- 自定义字符串的截取规则 -->
	 <trim prefix="where" suffixOverrides="and">
	 	<if test="id!=null">
		 	id=#{id} and
		 </if>
		 <if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
		 	last_name like #{lastName} and
		 </if>
		 <if test="email!=null and email.trim()!=&quot;&quot;">
		 	email=#{email} and
		 </if> 
		 <!-- ognl会进行字符串与数字的转换判断  "0"==0 -->
		 <if test="gender==0 or gender==1">
		 	 gender=#{gender}
		 </if>
	 </trim>
</select>

 

mybatis动态sql-(1)-多次条件判断If和OGNL

1、搭建数据库

tbl_employee表【d_id 是外键 对应 tbl_dept表】

id	last_name    gender	  email       d_id
1	   mike	       0      [email protected]      1
2          book        0      [email protected]    2
3          tom         1      [email protected]    2
4          jerry       1       [email protected]       1

tbl_dept表:

id    dept_name
1      开发部
2      测试部

2、编辑 javabean

特别要提醒:因为是在测试代码中,需要用到自定义Employee构造函数,所以这里为了能让mybatis正常使用反思,一定要添加Employee的无参构造函数。

Employee.java

package com.mybatis.bean;

public class Employee {
	private int id;
	private String lastName;
	private String email;
	private String gender;
	private Department department;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}
	
	public Department getDepartment() {
		return department;
	}

	public void setDepartment(Department department) {
		this.department = department;
	}

	@Override
	public String toString() {
		return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + "]";
	}

       /*****  关键是 这个地方啊 出了 问题 ****/
	public Employee() {
		super();
	}
	/*****/
	public Employee(int id,String lastName, String  email, String gender){
		this.id =id;
		this.lastName =lastName;
		this.email =email;
		this.gender =gender;
	}

}

Department.java

package com.mybatis.bean;

import java.util.List;

public class Department {
	
	private Integer id;
	private String departmentName;
        private List<Employee> employees;
        
        public List<Employee> getEmployees() {
		return employees;
	}
	public void setEmployees(List<Employee> employees) {
		this.employees = employees;
	}

	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getDepartmentName() {
		return departmentName;
	}
	public void setDepartmentName(String departmentName) {
		this.departmentName = departmentName;
	}
	@Override
	public String toString() {
		return "Department [id=" + id + ", departmentName=" + departmentName
				+ "]";
	}
	
	

}

三、编辑接口文件

EmployeeMapperDynamicSQL.java

package com.mybatis.mapper;

import java.util.List;

import com.mybatis.bean.Employee;

public interface EmployeeMapperDynamicSQL {

	//携带了哪个字段查询条件就带上这个字段的值
	public List<Employee> getEmpsByConditionIf(Employee employee);
	
}

四、SQL映射文件

<?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.mybatis.mapper.EmployeeMapperDynamicSQL">
<!-- 
上面的 namespace:名称空间;指定为接口的全类名
下面的 id:唯一标识被规定为接口方法名 【public Employee getEmpById(Integer id);】
下面的 resultType:返回值类型
下面的 #{id}:从传递过来的参数中取出id值
 -->
	
<!-- 
• if:判断
• choose (when, otherwise):分支选择;带了break的swtich-case
	如果带了id就用id查,如果带了lastName就用lastName查;只会进入其中一个
• trim 字符串截取(where(封装查询条件), set(封装修改条件))
• foreach 遍历集合
	 -->
	 <!-- 查询员工,要求,携带了哪个字段查询条件就带上这个字段的值 -->
	 <!-- public List<Employee> getEmpsByConditionIf(Employee employee); -->
<select id="getEmpsByConditionIf" resultType="com.mybatis.bean.Employee">
	 	select * from tbl_employee
	 	where
                <!-- where -->
	 	
		 	<!-- test:判断表达式(OGNL)
		 	OGNL参照PPT或者官方文档。
		 	  	 c:if  test
		 	从参数中取值进行判断
		 	
		 	遇见特殊符号应该去写转义字符:
		 	&&:
		 	-->
		 	<if test="id!=null">
		 		id=#{id}
		 	</if>
		 	<if test="lastName!=null &amp;&amp; lastName!=&quot;&quot;">
		 		and last_name like #{lastName}
		 	</if>
		 	<if test="email!=null and email.trim()!=&quot;&quot;">
		 		and email=#{email}
		 	</if> 
		 	<!-- ognl会进行字符串与数字的转换判断  "0"==0 -->
		 	<if test="gender==0 or gender==1">
		 	 	and gender=#{gender}
		 	</if>
	 	
	 </select>


</mapper>

五、全局配置文件

添加了,驼峰映射 大小写 自动转换 配置 setting。
因为从数据库中,选择出来了的就 只有5个字段,这5个字段,自动映射到Employee中,然后 d_id字段无法和bean中的department 属性映射,所以被废弃。department就为null了。

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

    <settings>
		<setting name="mapUnderscoreToCamelCase" value="true"/>
	</settings>

	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
				<property name="username" value="root" />
				<property name="password" value="Cool123!" />
			</dataSource>
		</environment>
	</environments>
	<!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 
	如果 数据库全局文件 和 子配置文件 不在同一个目录 ,就需要 /目录/目录/.../EmployeeMapper_old.xml
	-->
	<mappers>
	
	    <!-- 新方法操作mybatis 需要 的配置文件 -->
		<mapper resource="EmployeeMapperDynamicSQL.xml" />
	</mappers>
</configuration>

六、Junit单元测试

department属性,是没有赋值的,这里要注意一下。
sql语句的条件判断是OK的。

package com.mybatis.test;


import java.io.IOException;
import java.io.InputStream;
import java.util.List;

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 org.junit.Test;

import com.mybatis.bean.Employee;
import com.mybatis.mapper.EmployeeMapperDynamicSQL;


/**
 * 1、接口式编程
 * 	原生:		Dao		====>  DaoImpl
 * 	mybatis:	Mapper	====>  xxMapper.xml
 * 
 * 2、SqlSession代表和数据库的一次会话;用完必须关闭;
 * 3、SqlSession和connection一样她都是非线程安全。每次使用都应该去获取新的对象。(就是不要放在共享成员变量里面,A线程用完释放,B线程再用就为空了)
 * 4、mapper接口没有实现类,但是mybatis会为这个接口生成一个代理对象。
 * 		(将接口和xml进行绑定)
 * 		EmployeeMapper empMapper =	sqlSession.getMapper(EmployeeMapper.class);
 * 5、两个重要的配置文件:
 * 		mybatis的全局配置文件:包含数据库连接池信息,事务管理器信息等...系统运行环境信息
 * 		sql映射文件:保存了每一个sql语句的映射信息:
 * 					将sql抽取出来。	
 *
 */

public class MybatisTest {


	public SqlSessionFactory getSqlSessionFactory() throws IOException {
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		return new SqlSessionFactoryBuilder().build(inputStream);
	}
	
	@Test
	public void test_new() throws IOException {
		// 1、获取sqlSessionFactory对象
		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
		// 2、获取sqlSession对象
		SqlSession openSession = sqlSessionFactory.openSession();
		try {
			// 3、获取接口的实现类对象
			//会为接口自动的创建一个代理对象,代理对象去执行增删改查方法
			EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class);
			Employee employee = new Employee(3,"%m%","[email protected]","1");
			List<Employee> list = mapper.getEmpsByConditionIf(employee);
			for(Employee emp :list){
				System.out.println(emp);
				System.out.println(emp.getDepartment());

			}
		} finally {
			openSession.close();
		}

	}

}