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>

 

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments