查询的几种情况
// 1)查询单行数据返回单个对象
public Employee getEmployeeById(Integer id );
// 2) 查询多行数据返回对象的集合
public List<Employee> getAllEmps();
// 3) 查询单行数据返回Map集合
public Map<String,Object> getEmployeeByIdReturnMap(Integer id );
// 4) 查询多行数据返回Map集合
@MapKey("id") // 指定使用对象的哪个属性来充当map的key
public Map<Integer,Employee> getAllEmpsReturnMap();
<!--
查询单行数据返回Map集合
public Map<String, Object> getEmployeeByIdReturnMap(Integer id );
-->
<select id="getEmployeeByIdReturnMap" resultType="java.util.HashMap">
select id ,last_name,email,gender from tbl_employee where id = #{id}
</select>
<!--
查询多行数据返回Map集合
@MapKey("id") // 指定使用对象的哪个属性来充当map的key
public Map<Integer,Employee> getAllEmpsReturnMap();
-->
<select id="getEmpsReturnMap" resultType="com.atguigu.mybatis.beans.Employee">
select id ,last_name,email,gender from tbl_employee
</select>
自动映射类型取决于将数据存储成什么类型,上面的例子虽然最终是多条数据封装成map,但每一条数据的存储类型是Employ对象,所以resultType定义成Employ对象
-
Select
标签来定义查询操作。 -
Id
:唯一标识符。用来引用这条语句,需要和接口的方法名一致
-
parameterType
:参数类型。
可以不传,MyBatis会根据TypeHandler自动推断 -
resultType
:返回值类型。
别名或者全类名,如果返回的是集合,定义集合中元素的类型。不能和resultMap
同时使用
结果集的封装方式(重点)
resultType 自动映射(适合单表查询)
autoMappingBehavior
默认是PARTIAL
,表示开启自动映射的功能。唯一的要求是列名和JavaBean属性名一致- 如果
autoMappingBehavior
设置为null则会取消自动映射 - 数据库字段符合命名规范,POJO属性符合驼峰命名法,如A_COLUMN与aColumn,我们可以开启自动驼峰命名规则映射功能,
mapUnderscoreToCamelCase=true
不再举例,上面的例子都是自动映射方式
resultMap自定义映射(多表查询)
-
constructor
- 类在实例化时, 用来注入结果到构造方法中- idArg - ID 参数; 标记结果作为 ID 可以帮助提高整体效能
- arg - 注入到构造方法的一个普通结果
-
id
– 一个 ID 结果; 标记结果作为 ID 可以帮助提高整体效能 -
result
– 注入到字段或 JavaBean 属性的普通结果 -
association
– 一个复杂的类型关联;许多结果将包成这种类型- 嵌入结果映射 – 结果映射自身的关联,或者参考一个
-
collection
– 复杂类型的集- 嵌入结果映射 – 结果映射自身的集,或者参考一个
-
discriminator
– 使用结果值来决定使用哪个结果映射case – 基于某些值的结果映射
嵌入结果映射 – 这种情形结果也映射它本身,因此可以包含很多相同的元素,或者它可以参照一个外部的结果映射。
public class Employee {
private Integer id ;
private String lastName;
private String email ;
private Integer gender ;
//联合部门对象属性
private Department dept ;
}
/* 自定义映射
type: 最终结果集封装的类型
<id>: 完成主键列的映射
column: 数据库字段列名
property:对象的属性名
<result>:完成普通列的映射
*/
/*
需求: 查询员工对象, 并且查询员工所在 的部门信息.
*/
<select id="getEmpAndDept" resultMap="myEmpAndDept">
SELECT e.id eid , e.last_name, e.email,e.gender , d.id did , d.dept_name
FROM tbl_employee e , tbl_dept d
WHERE e.d_id = d.id AND e.id = #{id}
</select>
/*
eid last_name email gender did dept_name
1005 玛利亚老师 mly@sina.com 0 4 人事部
*/
<resultMap type="com.atguigu.mybatis.beans.Employee" id="myEmpAndDept">
<id column="eid" property="id"/>
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
/* 级联
<result column="did" property="dept.id"/>
<result column="dept_name" property="dept.departmentName"/>
*/
/*
association: 完成关联、联合属性的映射
property: 联合属性名
javaType: 联合属性的类型
*/
<association property="dept" javaType="com.atguigu.mybatis.beans.Department">
<id column="did" property="id" />
<result column="dept_name" property="departmentName"/>
</association>
</resultMap>
分步查询
实际的开发中,对于每个实体类都应该有具体的增删改查方法,也就是DAO层, 因此对于查询员工信息并且将对应的部门信息也查询出来的需求,就可以通过分步的方式
① 先通过员工的id查询员工信息
② 再通过查询出来的员工信息中的外键(部门id)查询对应的部门信息.
/*
association 使用分步查询:
需求: 查询员工信息并且查询员工所在的部门信息.
1. 先根据员工的id查询员工信息
2. 使用外键 d_id查询部门信息
*/
<!-- public Employee getEmpAndDeptStep(Integer id ); -->
<select id="getEmpAndDeptStep" resultMap="myEmpAndDeptStep">
select id, last_name, email,gender ,d_id from tbl_employee where id = #{id}
</select>
<resultMap type="com.atguigu.mybatis.beans.Employee" id="myEmpAndDeptStep">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
//分步查询
<association property="dept"
select="com.atguigu.mybatis.dao.DepartmentMapperResultMap.getDeptById"
column="{did=d_id}" fetchType="eager">
</association>
</resultMap>
分步查询多列值的传递
如果分步查询时,需要传递给调用的查询中多个参数,则需要将多个参数封装成Map来进行传递,语法如下: {k1=v1, k2=v2....}
在所调用的查询方发中,取值时就要参考Map的取值方式,需要严格的按照封装map时所用的key来取值.
association 或 collection的 fetchType属性
1)在association和collection标签中都可以设置fetchType,指定本次查询是否要使用延迟加载。默认为 fetchType=”lazy” ,如果本次的查询不想使用延迟加载,则可设置为fetchType=”eager”.
2)fetchType可以灵活的设置查询是否需要使用延迟加载,而不需要因为某个查询不想使用延迟加载将全局的延迟加载设置关闭.
collection
POJO中的属性可能会是一个集合对象,我们可以使用联合查询,并以级联属性的方式封装对象。使用collection标签定义对象的封装规则
public class Department {
private Integer id ;
private String departmentName ;
private List<Employee> emps ;
}
<select id="getDeptAndEmpsById" resultMap="myDeptAndEmps">
SELECT d.id did, d.dept_name ,e.id eid ,e.last_name ,e.email,e.gender
FROM tbl_dept d LEFT OUTER JOIN tbl_employee e ON d.id = e.d_id
WHERE d.id = #{id}
</select>
<resultMap type="com.atguigu.mybatis.beans.Department" id="myDeptAndEmps">
<id column="did" property="id"/>
<result column="dept_name" property="departmentName"/>
/*
property: 关联的属性名
ofType: 集合中元素的类型
*/
<collection property="emps" ofType="com.atguigu.mybatis.beans.Employee">
<id column="eid" property="id"/>
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
</collection>
</resultMap>
collection分布查询
实际的开发中,对于每个实体类都应该有具体的增删改查方法,也就是DAO层, 因此
对于查询部门信息并且将对应的所有的员工信息也查询出来的需求,就可以通过分步的方式完成查询。
① 先通过部门的id查询部门信息
② 再通过部门id作为员工的外键查询对应的部门信息.
<select id="getDeptAndEmpsByIdStep" resultMap="myDeptAndEmpsStep">
select id ,dept_name from tbl_dept where id = #{id}
</select>
<resultMap type="com.atguigu.mybatis.beans.Department" id="myDeptAndEmpsStep">
<id column="id" property="id"/>
<result column="dept_name" property="departmentName"/>
<collection property="emps"
select="com.atguigu.mybatis.dao.EmployeeMapper.getEmpsByDid"
column="id">
</collection>
</resultMap>