(5).Mybatis的关联查询

需要用到的数据库数据:

--创建数据库mybatis2
create database mybatis2 charset=utf8;
use mybatis2;
--创建数据表users
create table emp(
    e_no int(5) primary key auto_increment,
    e_name varchar(20),
    e_email varchar(50),
    d_deptno int(5)
) charset=utf8;
--emp表的测试数据
insert into emp(e_name, e_email, d_deptno) values("张三", "zhangsan@qq.com", 1);
insert into emp(e_name, e_email, d_deptno) values("李四", "lisi@qq.com", 1);
insert into emp(e_name, e_email, d_deptno) values("王五", "wangwu@qq.com", 2);
insert into emp(e_name, e_email, d_deptno) values("马六", "maliu@qq.com", 2);
insert into emp(e_name, e_email, d_deptno) values("张三丰", "zhangsanfeng@qq.com", 3);
insert into emp(e_name, e_email, d_deptno) values("李四光", "lisiguang@qq.com", 3);
insert into emp(e_name, e_email, d_deptno) values("老王", "laowang@qq.com", 4);
insert into emp(e_name, e_email, d_deptno) values("赵六", "zhanliu@qq.com", 4);
create table dept(
    d_deptno int(5) primary key auto_increment,
    d_name varchar(20),
    d_location varchar(10)
) charset=utf8;
--dept表的测试数据
insert into dept(d_name, d_location) values("开发部","一楼");
insert into dept(d_name, d_location) values("人事部","二楼");
insert into dept(d_name, d_location) values("运维中心","三楼");
insert into dept(d_name, d_location) values("账务部","四楼");

emp表中的d_deptno与dept表中的主键列进行关联。

在包com.qcc.entity下新建两个表对应的实体类:

emp表对应的实体类Emp(多方)

package com.qcc.entity;

public class Emp {
    private int no;
    private String name;
    private String email;
    private Dept dept;//在多方的实体类中将关联的字段修改为与之对应的实体对象属性,提供get/set方法。
    // Getter 和 Setter 方法略
    @Override
    public String toString() {
        return "Emp [no=" + no + ", name=" + name + ", email=" + email
                + ", dept=" + dept + "]";
    }

dept表对应的实体类Dept(一方)

package com.qcc.entity;

import java.util.List;

public class Dept {
    private int no;
    private String name;
    private String location;
    private List<Emp> emps;//在一方的实体类中添加多方的对象的集合,提供get/set方法。
    // Getter 和 Setter 方法略
    @Override
    public String toString() {
        return "Dept [no=" + no + ", name=" + name + ", location=" + location + "]";
    }
}

使用Mybatis进行数据库记录查询时,当表中的列名和类中的实体属性不一致时,需要对列名和实体属性进行映射:
常用的有两种方式:

 1.对数据库中的每一列起个与实体属性一致的别名;
 2.在实体类对应的mapper文件中,使用<resultMap>标签进行映射。

以查询dept信息为例:
在包com.qcc.mapping下新建deptMapper.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.qcc.mapping.deptMapper">

    <!-- 将查询字段手动映射成实体类的属性,以便mybatis对查询结果集进行封装成对象。 -->
    <select id="getAll" resultType="Dept">
        select
            d_deptno as no,
            d_name as name,
            d_location as location
        from dept 
    </select>

    <!-- 
        使用<resultMap>标签将查询字段与实体类的属性进行映射,方便其它地方引用 。
        表中主键字段使用<id />标签进行映射;
        普通字段用<result />标签映射;
        多方中关联一方对象的属性使用<association>标签映射;
        一方中多方的集合属性用<collection>标签映射;
        column指定表中的字段,property指定与字段相对应的类属性。
     -->
    <resultMap type="Dept" id="deptResultMap">
        <id column="d_deptno" property="no"/>
        <result column="d_name" property="name"/>
        <result column="d_location" property="location"/>
    </resultMap>

    <select id="getAll2" resultMap="deptResultMap">
        select * from dept
    </select>

</mapper>

新建测试类TestDeptQuery.java

package com.qcc.test;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import com.qcc.entity.Dept;
import com.qcc.utils.MybatisUtils;

public class TestDeptQuery {

    @Test
    public void testGetAll1(){
        SqlSession session = MybatisUtils.getSession(false);
        List<Dept> deptList = session.selectList("com.qcc.mapping.deptMapper.getAll");
        System.out.println("查询字段别名方式映射:");
        for (Dept dept : deptList) {
            System.out.println(dept);
        }
    }

    @Test
    public void testGetAll2(){
        SqlSession session = MybatisUtils.getSession(false);
        List<Dept> deptList = session.selectList("com.qcc.mapping.deptMapper.getAll2");
        System.out.println("使用<resultMap>标签方式进行映射");
        for (Dept dept : deptList) {
            System.out.println(dept);
        }
    }

}

测试结果如下:

查询字段别名方式映射:
Dept [no=1, name=开发部, location=一楼]
Dept [no=2, name=人事部, location=二楼]
Dept [no=3, name=运维中心, location=三楼]
Dept [no=4, name=账务部, location=四楼]
使用<resultMap>标签方式进行映射
Dept [no=1, name=开发部, location=一楼]
Dept [no=2, name=人事部, location=二楼]
Dept [no=3, name=运维中心, location=三楼]
Dept [no=4, name=账务部, location=四楼]

以上两种方式都可以在表字段与类属性不一致的情况下,将查询出的结果集正确地映射并封装成与之对应的java对象。


当查询emp的信息时,想把与之对应的dept的信息一并查询出来,此时需要在Emp类中添加关联的对象属性private Dept dept,同时在empMapper.xml文件中进行配置关联属性<association>标签。
empMapper.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.qcc.mapping.empMapper">

    <resultMap type="Emp" id="empResultMap">
        <id column="e_no" property="no"/>
        <result column="e_name" property="name"/>
        <result column="e_email" property="email"/>
        <!-- 
            关联的对象需使用association标签进行配置,两种方式:
            ① property的值对应实体属性,使用javaType=“Dept”来指定实体属性对应的java类型,
            然后在association标签体内逐个配置关联对象dept的属性与数据库表的映射信息,如下:
                <association property="dept" javaType="Dept">
                    <id column="d_deptno" property="no"/>
                    <result column="d_name" property="name"/>
                    <result column="d_location" property="location"/>
                </association>
         -->
        <!--
            ② property的值对应实体属性,resultMap对应结果集的类型,此处结果集的类型指定为:
            com.qcc.mapping.deptMapper这个命名空间下id值为deptResultMap的类型。
         -->
        <association property="dept" resultMap="com.qcc.mapping.deptMapper.deptResultMap"></association>
    </resultMap>

    <sql id="columns">e_no, e_name, e_email, d_deptno, d_name, d_location</sql>
    <select id="getAll" resultMap="empResultMap">
        select * from emp e inner join dept d on e.d_deptno=d.d_deptno
    </select>
</mapper>

关联映射测试代码:

@Test
public void test() {
    SqlSession session = MybatisUtils.getSession(false);
    List<Emp> empList = session.selectList("com.qcc.mapping.empMapper.getAll");
    for (Emp emp : empList) {
        System.out.println(emp);
    }
}

测试结果:

Emp [no=1, name=张三, email=zhangsan@qq.com, dept=Dept [no=1, name=开发部, location=一楼]]
Emp [no=2, name=李四, email=lisi@qq.com, dept=Dept [no=1, name=开发部, location=一楼]]
Emp [no=3, name=王五, email=wangwu@qq.com, dept=Dept [no=2, name=人事部, location=二楼]]
Emp [no=4, name=马六, email=maliu@qq.com, dept=Dept [no=2, name=人事部, location=二楼]]
Emp [no=5, name=张三丰, email=zhangsanfeng@qq.com, dept=Dept [no=3, name=运维中心, location=三楼]]
Emp [no=6, name=李四光, email=lisiguang@qq.com, dept=Dept [no=3, name=运维中心, location=三楼]]
Emp [no=7, name=老王, email=laowang@qq.com, dept=Dept [no=4, name=账务部, location=四楼]]
Emp [no=8, name=赵六, email=zhanliu@qq.com, dept=Dept [no=4, name=账务部, location=四楼]]

查询emp信息的同时,dept的相关联的信息也被查询出来了。


查询dept信息的时候,把dept下对应的所有员工信息查询出来,此时需要在Dept类中添加Emp对象的集合属性List<Emp> emps,同时在deptMapper.xml文件中进行配置关联属性标签。

<resultMap type="Dept" id="deptResultMap2">
    <id column="d_deptno" property="no"/>
    <result column="d_name" property="name"/>
    <result column="d_location" property="location"/>
    <!--
    一方的集合属性要配置对应的collection标签,使用ofType属性来指定集合中的数据类型。
    -->
    <collection property="emps" ofType="Emp" resultMap="com.qcc.mapping.empMapper.empResultMap">
    </collection>
</resultMap>

sql字符串的映射标签如下:

<select id="getAll3" resultMap="deptResultMap2">
    select * from dept inner join emp on dept.d_deptno = emp.d_deptno
</select>

测试dept关联emp信息的代码:

@Test
public void testGetAll3(){
    SqlSession session = MybatisUtils.getSession(false);
    List<Dept> deptList = session.selectList("com.qcc.mapping.deptMapper.getAll3");
    System.out.println("使用<resultMap>标签方式进行映射,查询关联的emp集合信息");
    for (Dept dept : deptList) {
        System.out.println(dept);
        List<Emp> emps = dept.getEmps();
        for (Emp emp : emps) {
            System.out.println("\t---->" + emp);
        }
    }
}

测试结果:

使用<resultMap>标签方式进行映射,查询关联的emp集合信息
Dept [no=1, name=开发部, location=一楼]
    ---->Emp [no=1, name=张三, email=zhangsan@qq.com, dept=Dept [no=1, name=开发部, location=一楼]]
    ---->Emp [no=2, name=李四, email=lisi@qq.com, dept=Dept [no=1, name=开发部, location=一楼]]
Dept [no=2, name=人事部, location=二楼]
    ---->Emp [no=3, name=王五, email=wangwu@qq.com, dept=Dept [no=2, name=人事部, location=二楼]]
    ---->Emp [no=4, name=马六, email=maliu@qq.com, dept=Dept [no=2, name=人事部, location=二楼]]
Dept [no=3, name=运维中心, location=三楼]
    ---->Emp [no=5, name=张三丰, email=zhangsanfeng@qq.com, dept=Dept [no=3, name=运维中心, location=三楼]]
    ---->Emp [no=6, name=李四光, email=lisiguang@qq.com, dept=Dept [no=3, name=运维中心, location=三楼]]
Dept [no=4, name=账务部, location=四楼]
    ---->Emp [no=7, name=老王, email=laowang@qq.com, dept=Dept [no=4, name=账务部, location=四楼]]
    ---->Emp [no=8, name=赵六, email=zhanliu@qq.com, dept=Dept [no=4, name=账务部, location=四楼]]

关联信息已经查询出来。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值