MyBatis学习笔记——查询Integer类型、Map类型、传入多个参数、多对一、一对多查询、分步查询的延迟加载

本文详细介绍了MyBatis中返回不同类型的查询结果,包括Integer和Map,以及如何处理Map集合中的单个和多个元素。此外,还讲解了如何传入多个参数,使用@Param自定义键,以及参数传递自定义Map集合的方法。同时,深入探讨了多对一查询和一对多查询的实现,包括association和collection的使用。最后,阐述了分步查询的实现和延迟加载的配置,以及如何单独设置某条语句的延迟加载情况。

public class Employee {
    private Integer id;
    private String eName;
    private Integer age;
    private String sex;
}

返回 Integer 类型结果

EmployeeMapper.java

/**
 * 查询员工总数
 * @return 员工总数
 */
Integer getEmpCount();

EmployeeMapper.xml

<!--查询员工总数-->
<!--MyBatis将常用的Java类型,都起了别名,因此不需要写全类名-->
<select id="getEmpCount" resultType="Integer">
    select count(*) from employee
</select>

测试

//查询员工总数
Integer count = employeeMapper.getEmpCount();
System.out.println(count);

返回 Map 类型结果

返回的 Map 集合中只有一个元素

  • 当 Map 集合中只有一个对象时,可以不指定 key,映射文件 resultType 的值要为 Map 类型

EmployeeMapper.java

/**
 * 根据id获取Map集合形式的员工信息
 * @param id
 * @return 某个员工的Map集合
 */
//当Map集合中只有一个对象时,可以不指定key,映射文件resultType的值要为Map类型
Map<String,Employee> getEmpMapById(String id);

EmployeeMapper.xml

<!--以Map集合形式查询某个员工的信息-->
<select id="getEmpMapById" resultType="java.util.HashMap">
    select * from employee where id = #{id}
</select>

测试

//以Map集合方式获取一个员工信息
Map<String, Employee> employee = employeeMapper.getEmpMapById("3");
System.out.println(employee);

返回的 Map 集合中有多个元素

  • 当 Map 集合中有多个对象时,要通过@MapKey指定查询结果中的哪个属性为 key
  • 若指定的 key 不存在,则 key=null
  • 映射文件 resultType 的值可以为 Map 类型,也可以为 Map 的 Value 类型

EmployeeMapper.java

/**
* 查询员工信息
* @return 以Map集合返回Employee
*/
//当Map集合中有多个对象时,要通过@MapKey的value属性指定谁为key,
//若指定的key不存在,则key=null,且使用该注解后,映射文件resultType的值可以不为Map类型
@MapKey(value="id")//让查询结果中的id作为key
Map<String,Employee> getEmpMaps();
<!--以Map集合形式查询全部员工信息-->
<select id="getEmpMaps" resultType="Employee"><!--resultType="java.util.HashMap"也可以-->
    select * from employee
</select>

测试

//以Map集合方式获取全部员工信息
Map<String, Employee> empMaps = employeeMapper.getEmpMaps();
System.out.println(empMaps);

传入多个参数

使用 MyBatis 默认的键获取参数

当方法中形参的个数大于1时,MyBatis 会将参数封装为 Map 对象,key 按照形参的顺序依次为arg0-argNparam1-paramN,在配置文件中可以根据 key 获取对应的参数值。

EmployeeMapper.java

/**
 * 根据id和name获取Employee
 * @param id
 * @param name
 * @return Employee
 */
//当传递多个参数时,MyBatis会将参数封装为Map对象,键为arg0-argN或param1-paramN
Employee getEmployeeByIdAndName(String id, String name);

EmployeeMapper.xml

<!--Employee getEmployeeByIdAndName(String id, String name);-->
<select id="getEmployeeByIdAndName" resultType="com.mcc.MyBatis.bean.Employee">
    select * from employee where id = #{param1} and ename = #{param2}
</select>

测试

//根据id和name获取员工信息
Employee employee = employeeMapper.getEmployeeByIdAndName("3", "mcc");
System.out.println(employee);

使用 @Param 自定义键

可以通过@Param注解,自定义参数在 Map 集合中的 key。

EmployeeMapper.java

/**
 * 根据name和age获取Employee
 * @param name
 * @param age
 * @return Employee
 */
//通过@Param注解,指定参数在Map集合中的key
Employee getEmployeeByNameAndAge(@Param("eName") String name, @Param("age") Integer age);

EmployeeMapper.xml

<!--Employee getEmployeeByNameAndAge(@Param("eName") String name, @Param("age") String age);-->
<select id="getEmployeeByNameAndAge" resultType="Employee">
    select * from employee where ename = #{eName} and age = #{age}
</select>

测试

//根据name和age获取员工信息
Employee employee = employeeMapper.getEmployeeByNameAndAge("admin", 20);
System.out.println(employee);

参数传递自定义 Map 集合

EmployeeMapper.java

/**
 * 根据Map获取员工信息
 * @param map
 * @return Employee
 */
Employee getEmpByMap(Map<String,Object> map);

EmployeeMapper.xml

<!--Employee getEmpByMap(Map<String,Object> map);-->
<select id="getEmpByMap" resultType="Employee">
    select * from employee where id = #{id} and sex = #{sex}
</select>

测试

//根据Map查询员工信息,假设根据id和sex查找
Map<String,Object> map = new HashMap<String,Object>();
map.put("id",1);
map.put("sex","男");
Employee employee = employeeMapper.getEmpByMap(map);
System.out.println(employee);

多对一查询

Employee.java

public class Employee {
    private Integer id;
    private String eName;
    private Integer age;
    private String sex;
    private Department dept;
}

Department.java

public class Department {
    private String id;
    private String dName;
    private List<Employee> empList;
}

自定义映射关系

需求:获取所有员工以及所属的部门信息

当返回的对象包括其他对象时,如 Employee 中包含 Department 对象,需要使用resultMap自定义映射,标签中的中属性:

  • id:设置主键的映射关系
  • result:设置非主键字段的映射关系
  • column:查询到的字段名
  • property:需要映射到的 JavaBean 的属性,支持级联赋值,如为 Employee 对象的 Department dept 属性赋值,可以写成dept.属性

EmpDeptMapper.java

/**
 * 获取每个部门的所有员工
 * @return List<Employee>
 */
List<Employee> getDeptAllEmps();

EmpDeptMapper.xml

<resultMap id="EmpMap01" type="Employee">
   <!--id:设置主键的映射关系-->
    <id column="eid" property="id"/>
    <!--result:设置非主键字段的映射关系-->
    <result column="eName" property="eName"/>
    <result column="age" property="age"/>
    <result column="sex" property="sex"/>
    <result column="did" property="dept.id"/>
    <result column="dName" property="dept.dName"/>
</resultMap>

<!--List<Employee> getDeptAllEmps();-->
<select id="getDeptAllEmps" resultMap="EmpMap02">
    select e.id eid,e.eName,e.age,e.sex,d.id did,d.dName 
    from department d 
        left join employee e 
            on d.id = e.departmentId
</select>

测试:

List<Employee> employees = empDeptMapper.getDeptAllEmps();
System.out.println(employees);

使用 association 实现自定义映射

上述情况,为 Employee 的 Department 属性赋值时,可以使用association标签实现,属性:

  • property:为哪个属性赋值
  • javaType:该属性的 java 类型

EmpDeptMapper.xml

<resultMap id="EmpMap02" type="Employee">
    <id column="eid" property="id"/>
    <result column="eName" property="eName"/>
    <result column="age" property="age"/>
    <result column="sex" property="sex"/>
    <association property="dept" javaType="com.mcc.MyBatis.bean.Department">
        <id column="did" property="id"/>
        <result column="dName" property="dName"/>
    </association>
</resultMap>

<!--List<Employee> getDeptAllEmps();-->
<select id="getDeptAllEmps" resultMap="EmpMap02">
    select e.id eid,e.eName,e.age,e.sex,d.id did,d.dName 
    from department d 
        left join employee e 
            on d.id = e.departmentId
</select>

分步查询

分步查询:将一次复杂查询分解为两次简单查询,将第一次的查询结果作为参数,传入第二次查询中,最后返回最终结果。

分步查询需要使用association或collection标签中的select属性:

  • select:第二步查询需要调用的方法的全类名
  • column:传入第二步调用的方法中的参数

需求:获取指定 id 的员工以及所属的部门信息

步骤:首先先查询指定 id 的员工信息,再将员工的 departmentId 作为参数(第二步的查询条件)传递给查询部门信息的方法

EmpDeptMapper.java

/**
 * 根据id查询员工信息,使用分步查询完成
 * @param id
 * @return Employee
 */
Employee getEmpByIdStep(String id);

DepartmentMapper.java

/**
 * 根据id获取部门信息
 * @param id
 * @return Department
 */
Department getDept(String id);

EmpDeptMapper.xml

<resultMap id="EmpStepMap" type="Employee">
    <id column="id" property="id"/>
    <result column="eName" property="eName"/>
    <result column="age" property="age"/>
    <result column="sex" property="sex"/>
    <!--执行 DepartmentMapper.java 中的 getDept() 方法,获取部门信息-->
    <association property="dept" select="com.mcc.MyBatis.mapper.DepartmentMapper.getDept" column="did"/>
</resultMap>

<!--Employee getEmpByIdStep(String id);-->
<select id="getEmpByIdStep" resultMap="EmpStepMap">
    select id,eName,age,sex,departmentId did from employee where id = #{id}
</select>

DepartmentMapper.xml

<mapper namespace="com.mcc.MyBatis.mapper.DepartmentMapper">

    <select id="getDept" resultType="com.mcc.MyBatis.bean.Department">
        select id,dName from department where id = #{id}
    </select>

</mapper>

一对多查询

Employee.java

public class Employee {
    private Integer id;
    private String eName;
    private Integer age;
    private String sex;
    private Department dept;
}

Department.java

public class Department {
    private String id;
    private String dName;
    private List<Employee> empList;
}

使用 collection 实现自定义映射

需求:根据 id 查询部门信息,包括部门内的所有员工

需要使用到collection标签,改标签内的属性:

  • property:为哪个属性赋值,该属性为集合类型
  • ofType:集合内存储的元素的类型

EmpDeptMapper.java

/**
 * 根据部门id获取部门及部门内所有员工信息
 * @param id
 * @return Department
 */
Department getDeptEmpsById(String id);

EmpDeptMapper.xml

<resultMap id="DeptEmps01" type="Department">
    <id column="did" property="id"/>
    <result column="dName" property="dName"/>
    <!--
        collection:处理数据是集合的问题,即一对多的问题
        ofType:指定集合中保存的数据类型,不需要指定javatype
    -->
    <collection property="empList" ofType="Employee">
        <id column="eid" property="id"/>
        <result column="eName" property="eName"/>
        <result column="age" property="age"/>
        <result column="sex" property="sex"/>
    </collection>
</resultMap>

<!--Department getDeptEmpsById(String id);-->
<select id="getDeptEmpsById" resultMap="DeptEmps01">
    select d.id did,d.dName,e.id eid,e.eName,e.age,e.sex,e.departmentId
    from department d left join employee e
        on d.id = e.departmentId
            where d.id = #{id}
</select>

测试:

Department dept = empDeptMapper.getDeptById("RS");
System.out.println(dept);

分步查询

可以使用分步查询,实现上面的需求:

步骤:先根据 id 查找部门信息,再根据 id 查找部门内的所有员工

使用collection标签的select属性,指定第二步要执行的方法。

EmpDeptMapper.java

/**
 * 根据id查找部门
 * @param id
 * @return Department
 */
Department getDeptById(String id);

/**
 * 根据部门id查找所有员工
 * @param departmentId
 * @return
 */
List<Employee> getDeptEmpsStepById(String departmentId);

EmpDeptMapper.xml

<resultMap id="DeptEmps02" type="Department">
    <id column="id" property="id"/>
    <result column="dName" property="dName"/>
    <collection property="empList" select="com.mcc.MyBatis.mapper.EmpDeptMapper.getDeptEmpsStepById" column="id"/>
    <!--
        当查询的条件有多个时,可以通过Map形式传递参数,如:根据id和dName查询,则column="{id=id,dName=dName}",
        此时,select的另外一个sql语句中,#{}要根据传递的key获取传递的参数
    -->
</resultMap>

<!--使用分步查询,根据部门id查找该部门的信息,以及该部门下的全部员工-->
<!--Department getDeptById(String id);-->
<select id="getDeptById" resultMap="DeptEmps02">
    select id,dName from department where id = #{id}
</select>

<!--List<Employee> getDeptEmpsStepById(String departmentId);-->
<select id="getDeptEmpsStepById" resultType="Employee">
    select id,eName,age,sex,departmentId from employee where departmentId = #{departmentId}
</select>

分步查询的延迟加载

设置延迟加载

什么是延迟加载?

  • 设置延迟加载,只有用到查询到的属性时,才会执行sql语句,没有用到时,不会执行
  • 延迟加载只有在分步查询中才会生效

实现方式:

在核心配置文件 mybatis-config.xml 中,配置settings

  • lazyLoadingEnabled:是否开启延迟加载,默认为false
  • aggressiveLazyLoading:是否查询全部数据,默认为true
  • lazyLoadingEnabled=“true” 时,aggressiveLazyLoading=“false”
    lazyLoadingEnabled=“false” 时,aggressiveLazyLoading=“true”

mybatis-config.xml

<settings>
    <!-- mapUnderscoreToCamelCase:下划线格式转换为驼峰格式,如user_name => userName -->
    <setting name="mapUnderscoreToCamelCase" value="true"/>
    <!--
        设置延迟加载,只有用到查询到的属性时,才会执行sql语句,没有用到时,不会执行
        延迟加载只有在分步查询中才会生效
        lazyLoadingEnabled:是否开启延迟加载,默认为false
        aggressiveLazyLoading:是否查询全部数据,默认为true
        lazyLoadingEnabled="true"时,aggressiveLazyLoading="false"
        lazyLoadingEnabled="false"时,aggressiveLazyLoading="true"
    -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="aggressiveLazyLoading" value="false"/>
</settings>

测试:

Employee emp = empDeptMapper.getEmpByIdStep("5");
//测试延迟加载
System.out.println(emp.geteName());//只执行查询员工信息的语句,不执行查询员工所属部门的语句
System.out.println(emp.getDept());//执行查询员工所属部门的语句

单独设置某条语句的延迟加载情况

在 mybatis-config.xml 中设置的延迟加载对项目中所有的分步查询都有效,可以在分步查询语句中通过fetchType属性,设置或修改本条语句的延迟加载情况。

  • fetchType="lazy":开启延迟加载
  • fetchType="eager":关闭延迟加载
<resultMap id="EmpStepMap" type="Employee">
    <id column="id" property="id"/>
    <result column="eName" property="eName"/>
    <result column="age" property="age"/>
    <result column="sex" property="sex"/>
    <!--执行 DepartmentMapper.java 中的 getDept() 方法,获取部门信息-->
    <association property="dept" select="com.mcc.MyBatis.mapper.DepartmentMapper.getDept" column="did" fetchType="lazy"/>
</resultMap>
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值