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();
		}

	}

}

 

mybatis基础-关键注意点bean的构造函数问题

当我用Junit单元测试,来学习mybatis时:

mybatis的bean文件中,采用的是默认构造函数。

当bean需要自定义构造函数时,一定要记得顺便 添加一个 无参构函数。因为mybatis用到了反射。无参构造函数是必须的。

如果自定义构造函数后,忘记添加了默认无参构造函数,那么就会报错。说缺少(,,,)形式的构造函数,但是不会说缺少无参构造函数。这个要注意啦。

 

mybatis映射文件-(8)-resultMap关联查询之discriminator鉴别器

鉴别器:mybatis可以使用discriminator判断某列的值,然后根据某列的值改变封装行为。比如封装Employee:根据gender值
1、如果查出的是女生:就把部门信息查询出来,否则不查询;
2、如果是男生,把last_name这一列的值赋值给email;

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.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 + "]";
	}

}

Department.java

package com.mybatis.bean;

import java.util.List;

public class Department {
	
	private Integer id;
	private String departmentName;
	
	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
				+ "]";
	}
	
	

}

3、编辑接口文件

EmployeeMapper.java

package com.mybatis.mapper;

import com.mybatis.bean.Employee;

public interface EmployeeMapper {
		
	public Employee getEmpByIdStep(Integer id);

}

DepartmentMapper.java

package com.mybatis.mapper;

import com.mybatis.bean.Department;

public interface DepartmentMapper {
	
	public Department getDeptById(Integer id);

}

4、编辑sql映射文件

EmployeeMapper.xml

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

	<!--自定义某个javaBean的封装规则
	type:自定义规则的Java类型
	id:唯一id方便引用
	  -->
	  
	<!-- public Employee getEmpById(Integer id); -->
	<select id="getEmpByIdStep"  resultMap="MyEmpDis">
		select * from tbl_employee where id=#{id}
	</select>
	
	
	<!-- =======================鉴别器============================ -->
	<!-- <discriminator javaType=""></discriminator>
		鉴别器:mybatis可以使用discriminator判断某列的值,然后根据某列的值改变封装行为
		封装Employee:
			如果查出的是女生:就把部门信息查询出来,否则不查询;
			如果是男生,把last_name这一列的值赋值给email;
	 -->
	 <resultMap type="com.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类型 ,string 是 mybatis 对String类型 直接默认设置 的别名 -->
	 	<discriminator javaType="string" column="gender">
	 		<!--女生  resultType:指定封装的结果类型;不能缺少。/resultMap-->
	 		<case value="0" resultType="com.mybatis.bean.Employee">
	 			<association property="department" 
			 		select="com.mybatis.mapper.DepartmentMapper.getDeptById"
			 		column="d_id">
		 		</association>
	 		</case>
	 		<!--男生 ;如果是男生,把last_name这一列的值赋值给email; -->
	 		<case value="1" resultType="com.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>

DepartmentMapper.xml

<?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.DepartmentMapper">
	
	<!--public Department getDeptById(Integer id);  -->
	<select id="getDeptById" resultType="com.mybatis.bean.Department">
		select id,dept_name departmentName from tbl_dept where id=#{id}
	</select>

</mapper>

5、编辑全局配置文件:

mybatis-config.xml

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

	<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="Kitty521!" />
			</dataSource>
		</environment>
	</environments>
	<!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 
	如果 数据库全局文件 和 子配置文件 不在同一个目录 ,就需要 /目录/目录/.../EmployeeMapper_old.xml
	-->
	<mappers>
	    <!-- 新方法操作mybatis 需要 的配置文件 -->
		<mapper resource="EmployeeMapperPlus.xml"  />
		<mapper resource="DepartmentMapper.xml" />
	</mappers>
	
</configuration>

特别注意:分步查询需要 调用两句sql语句。因为这两句sql语句分布在两个不同的sql映射文件,所以两个sql映射文件都需要注册到 全局配置文件中。

 

mybatis映射文件-(7)-resultMap关联查询之非级联一对多分步查询

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.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 + "]";
	}

}

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
				+ "]";
	}
	
	

}

3、编辑接口文件

DepartmentMapper.java

package com.mybatis.mapper;

import com.mybatis.bean.Department;

public interface DepartmentMapper {
	
	//分步查询
	public Department getDeptByIdStep(Integer id);

}

EmployeeMapper.java

package com.mybatis.mapper;

import java.util.List;

import com.mybatis.bean.Employee;

public interface EmployeeMapperPlus {
	
	public List<Employee> getEmpsByDeptId(Integer deptId);

}

4、编辑sql映射文件

DepartmentMapper.xml

<?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.DepartmentMapper">
	
<!-- collection:分步查询 -->
	<resultMap type="com.mybatis.bean.Department" id="MyDeptStep">
		<id column="id" property="id"/>
		<id column="dept_name" property="departmentName"/>
		<collection property="employees" 
			select="com.mybatis.mapper.EmployeeMapperPlus.getEmpsByDeptId"
			column="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

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

	<!--自定义某个javaBean的封装规则
	type:自定义规则的Java类型
	id:唯一id方便引用
	  -->
	
	<!-- public List<Employee> getEmpsByDeptId(Integer deptId); -->
	<select id="getEmpsByDeptId" resultType="com.mybatis.bean.Employee">
		select * from tbl_employee where d_id=#{deptId}
	</select>

</mapper>

5、编辑全局配置文件:

mybatis-config.xml

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

	<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="Kitty521!" />
			</dataSource>
		</environment>
	</environments>
	<!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 
	如果 数据库全局文件 和 子配置文件 不在同一个目录 ,就需要 /目录/目录/.../EmployeeMapper_old.xml
	-->
	<mappers>
	    <!-- 新方法操作mybatis 需要 的配置文件 -->
		<mapper resource="EmployeeMapperPlus.xml"  />
		<mapper resource="DepartmentMapper.xml" />
	</mappers>
	
</configuration>

特别注意:分步查询需要 调用两句sql语句。因为这两句sql语句分布在两个不同的sql映射文件,所以两个sql映射文件都需要注册到 全局配置文件中。

6、补充说明

分步查询中:子句查询时(无论是association 还是 collection 标签),传入多个参数问题,延迟加载设置:

### 举例:
### fetchType="lazy" 代表子句执行时,用的是延迟加载。
### - lazy:延迟  
### - eager:立即

### 子查询 多个入参问题
### column="{deptId=id}" 代表 sql字段的 id ,传入给 子句查询中的 deptId 入参
### 将多列的值封装成map;column="{key1=column1,key2=column2}"  来传给子查询的入参

<collection property="employees" 
	select="com.mybatis.mapper.EmployeeMapperPlus.getEmpsByDeptId"
	column="{deptId=id}" fetchType="lazy">
</collection>

 

 

 

mybatis映射文件-(6)-resultMap关联查询之非级联一对多一步查询

前面提到的关联查询中,bean里面的 某个属性就是一个对象,属于 一对一映射:可以采用一步查询,级联赋值 或者  采用分步查询 ,单独赋值。现在如果 bean的某个属性是 一个集合,属于一对多映射,那么 查询结果 就不能用级联赋值了。级联赋值 是 一对一 关系映射中的 一种方法。


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      测试部

数据库测试:

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 =1

2、编辑 javabean

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 + "]";
	}

}

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
				+ "]";
	}
	
	

}

3、编辑接口文件

DepartmentMapper.java

package com.mybatis.mapper;

import com.mybatis.bean.Department;

public interface DepartmentMapper {
	
	//增强版 还能查出员工
	public Department getDeptByIdPlus(Integer id);

}

4、编辑sql映射文件

DepartmentMapper.xml

<?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.DepartmentMapper">
	<!-- 
	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.mybatis.bean.Department" id="MyDept">
		<id column="did" property="id"/>
		<result column="dept_name" property="departmentName"/>
		<!-- 
			collection定义关联集合类型的属性的封装规则 
			ofType:指定集合里面元素的类型
		-->
		<collection property="employees" ofType="com.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>
</mapper>

5、编辑全局配置文件:

mybatis-config.xml

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

	<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="Kitty521!" />
			</dataSource>
		</environment>
	</environments>
	<!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 
	如果 数据库全局文件 和 子配置文件 不在同一个目录 ,就需要 /目录/目录/.../EmployeeMapper_old.xml
	-->
	<mappers>
		<mapper resource="DepartmentMapper.xml" />
	</mappers>
	
</configuration>

6、单元测试:

MybatisTest.java

package com.mybatis.test;


import java.io.IOException;
import java.io.InputStream;

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.Department;
import com.mybatis.bean.Employee;
import com.mybatis.mapper.DepartmentMapper;
import com.mybatis.mapper.EmployeeMapperPlus;


/**
 * 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、获取接口的实现类对象
			//会为接口自动的创建一个代理对象,代理对象去执行增删改查方法

//			EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class);
//			Employee employee = mapper.getEmpByIdStep(1);
//			System.out.println(mapper.getClass());
//			System.out.println(employee);
//			System.out.println(employee.getDepartment());
			
			DepartmentMapper mapper = openSession.getMapper(DepartmentMapper.class);
			Department department = mapper.getDeptByIdPlus(1);
			System.out.println(mapper.getClass());
			System.out.println(department);
			System.out.println(department.getEmployees());

		} finally {
			openSession.close();
		}

	}

}

 

mybatis映射文件-(5)-resultMap关联查询之分步查询与非级联赋值

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.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 + "]";
	}

}

Department.java

package com.mybatis.bean;

import java.util.List;

public class Department {
	
	private Integer id;
	private String departmentName;

	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
				+ "]";
	}
	
	

}

3、编辑接口文件

EmployeeMapper.java

package com.mybatis.mapper;

import java.util.List;

import com.mybatis.bean.Employee;

public interface EmployeeMapper {
	
	
	public Employee getEmpByIdStep(Integer id);
	

}

DepartmentMapper.java

package com.mybatis.mapper;

import com.mybatis.bean.Department;

public interface DepartmentMapper {
	
	public Department getDeptById(Integer id);
	
}

4、编辑sql映射文件

DepartmentMapper.xml

<?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.DepartmentMapper">
	<!--public Department getDeptById(Integer id);  -->
	<select id="getDeptById" resultType="com.mybatis.bean.Department">
		select id,dept_name departmentName from tbl_dept where id=#{id}
	</select>
	
</mapper>

EmployeeMapper.xml

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

	<!--自定义某个javaBean的封装规则
	type:自定义规则的Java类型
	id:唯一id方便引用
	  -->
        <!-- 使用association进行分步查询:
		1、先按照员工id查询员工信息
		2、根据查询员工信息中的d_id值去部门表查出部门信息
		3、部门设置到员工中;
	 -->
	 
	 <!--  id  last_name  email   gender    d_id   -->
	 <resultMap type="com.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="department" 
	 		select="com.mybatis.mapper.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>
</mapper>

5、编辑全局配置文件:

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

	<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="Kitty521!" />
			</dataSource>
		</environment>
	</environments>
	<!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 
	如果 数据库全局文件 和 子配置文件 不在同一个目录 ,就需要 /目录/目录/.../EmployeeMapper_old.xml
	-->
	<mappers>
	    <!-- 新方法操作mybatis 需要 的配置文件 -->
		<mapper resource="EmployeeMapper.xml" />
	</mappers>
	
</configuration>

特别强调,上面的配置文件忘记添加了<mapper resource="DepartmentMapper.xml" />

<mappers>
<!-- 因为涉及到分步查询,所以每一步,查询语句都要注册好,
一开始下面第一句 sql 映射文件 没有注册,结果就报错了 -->
<mapper resource="DepartmentMapper.xml" />
<mapper resource="EmployeeMapperPlus.xml" />

</mappers>

因为没有添加<mapper resource="DepartmentMapper.xml" />导致报错结果:

org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.mybatis.mapper.DepartmentMapper.getDeptById
### The error may exist in EmployeeMapperPlus.xml
### The error may involve com.mybatis.mapper.EmployeeMapperPlus.getEmpByIdStep
### The error occurred while handling results
### SQL: select * from tbl_employee where id=?          and 1=1
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for com.mybatis.mapper.DepartmentMapper.getDeptById
	at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
	at 

所以一定要添加啊,<mapper resource="DepartmentMapper.xml" />

6、单元测试:

package com.mybatis.test;


import java.io.IOException;
import java.io.InputStream;

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.EmployeeMapperPlus;


/**
 * 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、获取接口的实现类对象
			//会为接口自动的创建一个代理对象,代理对象去执行增删改查方法
			EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class);
			Employee employee = mapper.getEmpByIdStep(1);
			System.out.println(mapper.getClass());
			System.out.println(employee);
			System.out.println(employee.getDepartment());
		} finally {
			openSession.close();
		}

	}

}

7、延迟加载

<!-- 可以使用延迟加载(懒加载);(按需加载)
	 	Employee==>Dept:
	 		我们每次查询Employee对象的时候,都将一起查询出来。
	 		部门信息在我们使用的时候再去查询;
	 		分段查询的基础之上加上两个配置:
 -->

这两个配置,需要写在mybatis全局配置中:

<!-- 
	2、settings包含很多重要的设置项
	setting:用来设置每一个设置项
		name:设置项名
		value:设置项取值
 -->
<settings>
	<!-- 配置驼峰命名法 <setting name="mapUnderscoreToCamelCase" value="true"/> -->
	<!-- 配置oracle 字段内容 null类型 兼容 <setting name="jdbcTypeForNull" value="NULL"/> -->
		
	<!--下面这两个是用来开启延迟加载用的,显示的指定每个我们需要更改的配置的值,即使他是默认的。防止版本更新带来的问题  -->
	<setting name="lazyLoadingEnabled" value="true"/>
	<setting name="aggressiveLazyLoading" value="false"/>
</settings>

8、补充说明

分步查询中:子句查询时(无论是association 还是 collection 标签),传入多个参数问题,延迟加载设置:

### 举例:
### fetchType="lazy" 代表子句执行时,用的是延迟加载。
### - lazy:延迟  
### - eager:立即

### 子查询 多个入参问题
### column="{deptId=id}" 代表 sql字段的 id ,传入给 子句查询中的 deptId 入参
### 将多列的值封装成map;column="{key1=column1,key2=column2}"  来传给子查询的入参

<association property="department" 
	 select="com.mybatis.mapper.DepartmentMapper.getDeptById"
	 column="{id=d_id}" fetchType="lazy">
</association>

 

mybatis映射文件-(4)-resultMap关联查询之一步查询与级联赋值

sql查询结果,自动映射方法

•1、全局setting设置
–autoMappingBehavior默认是PARTIAL,开启自动映射的功能。唯一的要求是列名和javaBean属性名一致
–如果autoMappingBehavior设置为null则会取消自动映射
–数据库字段命名规范,POJO属性符合驼峰命名法,如A_COLUMN->aColumn,我们可以开启自动驼峰命名规则映射功能,mapUnderscoreToCamelCase=true。

•2、sql语句查询时,使用别名,完成bean的映射。

•3、自定义resultMap,实现高级结果集映射,完成自定义封装查询结果。

sql映射文件中   sql语句   的 resultMap 与 resultType 只能二选一。


测试数据库:

创建数据库:【第一次写的时候,居然写成tbl_employee{},sql语句没有{},应该是()  】

create table tbl_employee(
  id int(11) primary key auto_increment,
  last_name varchar(255),
  gender char(1),
  email varchar(255)
)

添加数据:

id	last_name    gender	     email
1	   mike	       0     [email protected]

resultMap:简单映射

Junit单元测试:
EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class);
Employee employee = mapper.getEmpById(1);
System.out.println(mapper.getClass());
System.out.println(employee);

接口文件:
public Employee getEmpById(Integer id);

sql映射文件:
<!--自定义某个javaBean的封装规则
type:自定义规则的Java类型
id:唯一id方便引用
 -->
<resultMap type="com.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>

eclipse:控制台输出数据库接口

Employee [id=1, lastName=mike, [email protected], gender=0]

resultMap:级联映射

1、新建雇员表:

create table tbl_employee(
  id int(11) primary key auto_increment,
  last_name varchar(255),
  gender char(1),
  email varchar(255)
)

2、添加雇员信息:

id	last_name    gender	     email
1	   mike	       0     [email protected]

3、添加部门表:

create table tbl_dept(
   id int(11) primary key auto_increment,
   dept_name varchar(255)
)

4、添加部门信息:

id    dept_name
1      开发部
2      测试部

5、添加表关联

下面是两条sql语句,第一条语句后面要写分号,这样才能顺利执行。

alter table tbl_employee add column d_id int(11);

alter table tbl_employee add CONSTRAINT fk_emp_dept 
FOREIGN key(d_id) REFERENCES tbl_dept(id)

6、

sql 客户端 查询:

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 =1

项目代码文件:

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 + "]";
	}

}

Department.java

package com.mybatis.bean;

import java.util.List;

public class Department {
	
	private Integer id;
	private String departmentName;
	
	
	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测试文件:
EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class);
Employee employee = mapper.getEmpAndDept(1);
System.out.println(employee);
System.out.println(employee.getDepartment());


接口文件:
public Employee getEmpAndDept(Integer id);

sql映射文件:
<!-- 
场景一:
	查询Employee的同时查询员工对应的部门
	Employee===Department
	一个员工有与之对应的部门信息;
	id  last_name  gender    d_id     did  dept_name (private Department dept;)
 -->
	 
<!--
	联合查询:级联属性封装结果集
  -->
<resultMap type="com.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="department.id"/>
	<result column="dept_name" property="department.departmentName"/>
</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>

sql映射文件也可以替换 采用  association标签方法:

<!-- 
	使用association定义关联的单个对象的封装规则;
 -->
<resultMap type="com.mybatis.bean.Employee" id="MyDifEmp2">
	<id column="id" property="id"/>
	<result column="last_name" property="lastName"/>
	<result column="gender" property="gender"/>
		
	<!--  association可以指定联合的javaBean对象
	property="department":指定哪个属性是联合的对象
	javaType:指定这个属性对象的类型[不能省略]
	-->
	<association property="department" javaType="com.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="MyDifEmp2">
	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>

 

 

 

mybatis映射文件-(3)-resultType与简单查询

在sql映射文件中,简单的查询结果用resultType,复杂的查询结果(关联查询)用resultMap。

一、返回list集合

单元测试:
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
List<Employee> like = mapper.getEmpsByLastNameLike("%e%");
for (Employee employee : like) {
	System.out.println(employee);
}

接口:
public List<Employee> getEmpsByLastNameLike(String lastName);

sql映射文件:
<!-- public List<Employee> getEmpsByLastNameLike(String lastName); -->
<!--resultType:如果返回的是一个集合,要写集合中元素的类型  -->
<select id="getEmpsByLastNameLike" resultType="com.mybatis.bean.Employee">
	select * from tbl_employee where last_name like #{lastName}
</select>

二、返回map

1、一个Employee 对应的 map
举例:{id=1, [email protected], last_name=mike, gender=0}

单元测试:
Map<String, Object> map = mapper.getEmpByIdReturnMap(1);
System.out.println(map);

接口:
//返回一条记录的map;key就是列名,值就是对应的值
public Map<String, Object> getEmpByIdReturnMap(Integer id);
	
sql映射文件:
<!--public Map<String, Object> getEmpByIdReturnMap(Integer id);  -->
 <select id="getEmpByIdReturnMap" resultType="map">
 	select * from tbl_employee where id=#{id}
 </select>

2、多个Employee对应的map

单元测试:
Map<String, Employee> map = mapper.getEmpByLastNameLikeReturnMap("%r%");
System.out.println(map);

接口:
//多条记录封装一个map:Map<Integer,Employee>:键是这条记录的主键,值是记录封装后的javaBean
//@MapKey:告诉mybatis封装这个map的时候使用哪个属性作为map的key
@MapKey("email")
public Map<String, Employee> getEmpByLastNameLikeReturnMap(String lastName);

sql映射文件:
<!--public Map<Integer, Employee> getEmpByLastNameLikeReturnMap(String lastName);  -->
 <select id="getEmpByLastNameLikeReturnMap" resultType="com.mybatis.bean.Employee">
 	select * from tbl_employee where last_name like #{lastName}
 </select>

测试结果:

{[email protected]=Employee [id=4, lastName=null, [email protected], gender=1]}