public List getEmpsByLastNameLike(String lastName);
<select id="getEmpsByLastNameLike" resultType="com.shen.mybaties.bean.Employee" >
select * from tbl_employee where last_name like #{lastName}
select>
注意:虽然是List集合,但是resultType
还是要写集合元素的类型,MyBatis会自动帮我们把结果集封装成指定元素的集合类型。
//返回一个记录的map,key就是列明,值就是对应的值
public Map getEmpByIdReturnMap(Integer id);
<select id="getEmpByIdReturnMap" resultType="map">
select * from tbl_employee where id = #{id}
select>
注意:这里的resultType="map"
,MyBatis给Map起了别名就是map
,返回的记录就会以Map的形式返回。
//多条记录封装一个map,Map:键是记录的某个属性,值是记录封装后的JavaBean
//告诉MyBatis封装这个map的时候,使用哪个属性作为map的key
@MapKey("lastName")
public Map getEmpsByLastNameReturnMap(String lastName);
注意:这里的Map,Key是指定的bean的某属性值,Value是记录封装的bean对象。
指定Key需要使用@MapKey
这个注解,它的value是bean对象的属性名称。
<select id="getEmpsByLastNameReturnMap" resultType="com.shen.mybaties.bean.Employee">
select * from tbl_employee where last_name like #{lastName}
select>
这里的resultType
依旧是Map中Value元素的类型。
public Employee getEmpById(Integer id);
<resultMap type="com.shen.mybaties.bean.Employee" id="MyEmp">
<id column="id" property="id"/>
<result column="Last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
resultMap>
这个是重点,即编写我们自己定制的映射规则。
(0)属性id:唯一id,用于引用,下面sql语句的resultMap
用这个id进行引用。
(1)子标签
:定义主键的映射规则,相比
,会有底层的优化。
(2)子标签
:定义普通列的映射规则
(3)(1)和(2)的子标签
:结果集的列名,和下面一一对应
(4)(1)和(2)的子标签
:javaBean的属性名,和上面一一对应
注意:若没有指定,则自动进行封装(找对应列名封装)。
<select id="getEmpById" resultMap="MyEmp">
select * from tbl_employee where id = #{id}
select>
增加bean
public class Department {
private Integer id;
private String departmentName;
public Department() {
super();
}
public Department(Integer id, String departmentName) {
super();
this.id = id;
this.departmentName = 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 + "]";
}
}
增加成员变量。
public class Employee {
private Integer id;
private String lastName;
private String email;
private String gender;
private Department dept;
每个员工都有一个部门信息。
public Employee getEmpAndDept(Integer id);
<resultMap type="com.shen.mybaties.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>
这是重点:其中的did和dept_name都是部门信息,后面的property使用级联属性封装结果集
,使用dept.id和dept.departmentName
。
<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>
这里的resultMap
引用的就是刚才的id,这里select出来的结果集列就用到了自定义的映射规则。
<resultMap type="com.shen.mybaties.bean.Employee" id="MyDifEmp2">
<id column="id" property="id"/>
<result column="last_name" property="lastName"/>
<result column="gender" property="gender"/>
<association property="dept" javaType="com.shen.mybaties.bean.Department">
<id column="did" property="id"/>
<result column="dept_name" property="departmentName"/>
association>
resultMap>
这里使用association标签进行联合对象的属性映射。
<resultMap type="com.shen.mybaties.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 property="dept"
select="com.shen.mybaties.dao.DepartmentMapper.getDeptById"
column="d_id">
association>
resultMap>
重点
:
中需要配置几个属性。
(1)select:表明当前属性是调用select指定的方法查出的结果,这里需要用到其他的select方法,我们需要编写对应的Mapper接口和Mapper XML文件。
(2)column:指定将哪一列的值传递给这个select方法(猜测只能传一个)。
Department属性的Mapper接口:
public interface DepartmentMapper {
public Department getDeptById(Integer id);
}
DepartmentMapper接口对应的xml文件:
<mapper namespace="com.shen.mybaties.dao.DepartmentMapper">
<select id="getDeptById" resultType="com.shen.mybaties.bean.Department">
select id,dept_name departmentName from tbl_dept where id = #{id};
select>
mapper>
可以看出:这个查询方法需要一个参数id,而在
中的column
中指定一个参数传进来,这个参数是上层结果集的某列。
EmployeeMapper的XML文件:
<select id="getEmpByIdStep" resultMap="MyEmpByStep">
select * from tbl_employee where id = #{id}
select>
这里看到:
(1)先进行员工信息的查询
(2)利用员工信息的某列,根据这列去查询部门信息
(3)再将部门信息整合到员工信息中。
在使用分布查询的基础上,我们可以简单的通过两个设置,来达到延迟加载的效果(懒加载)。
全局配置文件中加入如下两个设置:
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
settings>
注意点:
只能是单个的联合对象,而不能去加载一个对象的集合。
场景:查询部门的时候将部门对应的所有员工信息也查询出来。
public class Department {
private Integer id;
private String departmentName;
private List emps;
}
<resultMap type="com.shen.mybaties.bean.Department" id="MyDept">
<id column="did" property="id"/>
<result column="dept_name" property="departmentName"/>
<collection property="emps" ofType="com.shen.mybaties.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>
重点
:由于Department的emps属性为一个集合,所以封装的时候,要使用
标签来封装。
其中两个属性:
(1)property:表明是上层对象的哪一个属性名。
(2)ofType:表明集合内部的元素类型。(不要想当然,不是JavaType
)
<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>
这里我们使用连接查询(效果一样)。
<resultMap type="com.shen.mybaties.bean.Department" id="MyDeptStep">
<id column="id" property="id"/>
<result column="dept_name" property="departmentName"/>
<collection property="emps"
select="com.shen.mybaties.dao.EmployeeMapperPlus.getEmpsByDeptId"
column="id">collection>
resultMap>
<select id="getDeptByIdStep" resultMap="MyDeptStep">
select id,dept_name from tbl_dept where id = #{id}
select>
就像单元素的分步查询一样,但这里使用的是collection
而不是association
,它内部也有一个select
属性和column
属性,同样select负责第二步的查询语句,column负责传入select需要的参数。
public List getEmpsByDeptId(Integer deptId);
<select id="getEmpsByDeptId" resultType="com.shen.mybaties.bean.Employee">
select * from tbl_employee where d_id=#{deptId}
select>
上面两个是为了部门查询时,第二步查询员工信息的查询语句。
不管是单元素(association
)还是集合类型(collection
),进行后面步骤查询的时候,都需要一个select属性
,这里面规定一个外部的查询引用(namespace+select id)
,通常他都需要参数才能进行查询(#{XX}),同时有一个column属性
,是为了传入select需要的参数,column是上层查询的结果集的列名
。
解决办法:将多列的值封装map传递 ,column="{key1=column1,key2=column2}"
和
都有一个属性叫fetchType
,默认为lazy。
虽然在全局配置中,我们开启了延迟加载,但是可以在局部进行配置,仅对当前的封装生效。
fetchType有lazy
和eager
两个值,字面意思。
mybits可以使用discriminator判断某列的值,然后根据某列的值改变封装行为。
规则:
如果查出的是女生,就把部门信息查询出来,否则不查询。
如果是男生,把last_name这一列的值赋值给email。
<resultMap type="com.shen.mybaties.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"/>
<discriminator javaType="string" column="gender">
<case value="0" resultType="com.shen.mybaties.bean.Employee">
<association property="dept"
select="com.shen.mybaties.dao.DepartmentMapper.getDeptById"
column="d_id">
association>
case>
<case value="1" resultType="com.shen.mybaties.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>