Mybatis学习笔记——select相关知识(返回集合类型、自定义映射[联合查询|分步查询|集合属性封装|鉴别器])

返回List

编写接口方法

public List getEmpsByLastNameLike(String lastName);

编写sql语句

 
 
  <select id="getEmpsByLastNameLike" resultType="com.shen.mybaties.bean.Employee" >
    select * from tbl_employee where last_name like #{lastName}
  select>

注意:虽然是List集合,但是resultType还是要写集合元素的类型,MyBatis会自动帮我们把结果集封装成指定元素的集合类型。


返回Map

单条记录的Map

编写接口方法

    //返回一个记录的map,key就是列明,值就是对应的值
    public Map getEmpByIdReturnMap(Integer id);

编写sql语句

  
  <select id="getEmpByIdReturnMap" resultType="map">
    select * from tbl_employee where id = #{id}
  select>

注意:这里的resultType="map",MyBatis给Map起了别名就是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对象的属性名称。

编写sql语句

  
  <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的属性名,和上面一一对应
注意:若没有指定,则自动进行封装(找对应列名封装)。

编写sql语句

    
    
    <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

编写sql语句

    
    <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出来的结果集列就用到了自定义的映射规则。

利用association标签

自定义的映射规则

    
    <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标签进行联合对象的属性映射。


分步查询

利用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方法(猜测只能传一个)。

编写Mapper接口和Mapper XML

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>

测试

Mybatis学习笔记——select相关知识(返回集合类型、自定义映射[联合查询|分步查询|集合属性封装|鉴别器])_第1张图片
这里看到:
(1)先进行员工信息的查询
(2)利用员工信息的某列,根据这列去查询部门信息
(3)再将部门信息整合到员工信息中。

延迟加载

在使用分布查询的基础上,我们可以简单的通过两个设置,来达到延迟加载的效果(懒加载)。
全局配置文件中加入如下两个设置:

    <settings>
        
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="false"/>
    settings>

这样就可以达到延迟加载的效果,即用到才去查询。
Mybatis学习笔记——select相关知识(返回集合类型、自定义映射[联合查询|分步查询|集合属性封装|鉴别器])_第2张图片

注意点只能是单个的联合对象,而不能去加载一个对象的集合。


集合类型的属性封装

场景:查询部门的时候将部门对应的所有员工信息也查询出来。

public class Department {

    private Integer id;
    private String departmentName;
    private List emps;
}

collection嵌套结果集的方式

编写映射规则

    
    <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

sql语句

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

这里我们使用连接查询(效果一样)。

collection分步查询的方式

编写映射规则以及sql语句

    <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需要的参数。

编写第二步查询的Mapper接口方法和Mapper XML

    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有lazyeager两个值,字面意思。

discriminator鉴别器

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>

你可能感兴趣的:(Mybatis)