mybatis级联查询

什么是mybatis级联查询

MyBatis级联查询是指在查询操作中,通过一次查询关联的多个表格,并将结果映射到一个复杂的对象中。通常情况下,关联查询需要多次查询数据库并手动组装结果,而级联查询则通过MyBatis的特性来自动完成这个过程。

在MyBatis中,级联查询可以通过嵌套查询语句或使用关联映射来实现。嵌套查询语句是指在一个查询语句中嵌套另一个查询语句,通过在查询结果中引用另一个查询来实现级联查询。关联映射是指通过配置文件中的关联映射标签来定义对象之间的关联关系,然后在查询操作中通过关联映射来实现级联查询。

一对一级联查询

创建两张表一张为用户表一张为部门表

create table sys_user
(
    user_id     bigint auto_increment
        primary key,
    username    varchar(50)  not null comment '用户名',
    password    varchar(100) null comment '密码',
    salt        varchar(20)  null comment '盐',
    email       varchar(100) null comment '邮箱',
    mobile      varchar(100) null comment '手机号',
    status      tinyint      null comment '状态  0:禁用   1:正常',
    dept_id     bigint       null comment '部门ID',
    create_time datetime     null comment '创建时间',
    constraint username
        unique (username)
)
    comment '系统用户' charset = utf8mb4;


create table sys_dept
(
    dept_id   bigint auto_increment
        primary key,
    parent_id bigint            null comment '上级部门ID,一级部门为0',
    name      varchar(50)       null comment '部门名称',
    order_num int               null comment '排序',
    del_flag  tinyint default 0 null comment '是否删除  -1:已删除  0:正常'
)
    comment '部门管理' charset = utf8mb4;

创建两个相对应的实体类

public class Dept{
private List<User> list;
    private Long deptId;
    private Long parentId;
    private String name;
    private Integer orderNum;
    private Integer delFlag;
}

public class User{
	private Dept dept;
    private Long userId;
    private String username;
    private String password;
    private String salt;
    private String email;
    private String mobile;
    private Integer status;
    private Long deptId;
    private Date createTime;
}

UserMapper.xml查询
方式一:
根据用户id查询部门

//测试类中
User user = userMapper.selectByPrimaryKey(1L);
user.setDept(deptMapper.selectByPrimaryKey(user.getDeptId()));
System.out.println(user);
<resultMap id="BaseResultMap" type="cn.hx.mybatis.entity.User">
        <id property="userId" column="user_id" jdbcType="BIGINT"/>
        <result property="username" column="username" jdbcType="VARCHAR"/>
        <result property="password" column="password" jdbcType="VARCHAR"/>
        <result property="salt" column="salt" jdbcType="VARCHAR"/>
        <result property="email" column="email" jdbcType="VARCHAR"/>
        <result property="mobile" column="mobile" jdbcType="VARCHAR"/>
        <result property="status" column="status" jdbcType="TINYINT"/>
        <result property="deptId" column="dept_id" jdbcType="BIGINT"/>
        <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
    </resultMap>

<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from sys_user
        where user_id = #{userId,jdbcType=BIGINT}
    </select>

resultMap 中自定义的id需要和select标签中resultMap里面的自定义的名称相同(表示sql查询到的内容需要映射到resultMap 中进行封装)parameterType是用来指定SQL语句中的参数类型的属性

方式二
嵌套查询,通过执行另外一个SQL映射语句来返回预期的复杂类型

//根据用户id来查询部门
User user = userMapper.selectByPrimaryKeyWithDept(1L);
System.out.println(user);
<resultMap id="BaseResultMapWithDept" type="cn.hx.mybatis.entity.User">
        <id property="userId" column="user_id" jdbcType="BIGINT"/>
        <result property="username" column="username" jdbcType="VARCHAR"/>
        <result property="password" column="password" jdbcType="VARCHAR"/>
        <result property="salt" column="salt" jdbcType="VARCHAR"/>
        <result property="email" column="email" jdbcType="VARCHAR"/>
        <result property="mobile" column="mobile" jdbcType="VARCHAR"/>
        <result property="status" column="status" jdbcType="TINYINT"/>
        <result property="deptId" column="dept_id" jdbcType="BIGINT"/>
        <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
        //property=需要关联的对象"  column="需要传输的属性" select="需要传输到什么地方"
        <association property="dept" column="dept_id" select="cn.hx.mybatis.mapper.DeptMapper.selectByPrimaryKey"/>
    </resultMap>

<select id="selectByPrimaryKeyWithDept" parameterType="java.lang.Long" resultMap="BaseResultMapWithDept">
        select
        <include refid="Base_Column_List"/>
        from sys_user
        where user_id = #{userId,jdbcType=BIGINT}
    </select>
   

< association property=“dept” column=“dept_id” select=“cn.hx.mybatis.mapper.DeptMapper.selectByPrimaryKey”/>它表示在查询结果中,将会有一个名为"dept"的属性与"dept_id"列进行关联,并且通过调用"cn.hx.mybatis.mapper.DeptMapper.selectByPrimaryKey"方法来查询与该属性关联的部门信息
具体解释如下:

  • association标签用于配置关联映射。
  • property=“dept"表示要将查询结果映射到的目标对象中的属性名为"dept”。
  • column=“dept_id"表示关联的列名为"dept_id”,即通过该列与目标对象进行关联。
  • select="cn.hx.mybatis.mapper.DeptMapper.selectByPrimaryKey"表示通过调用"cn.hx.mybatis.mapper.DeptMapper"接口中的"selectByPrimaryKey"方法来查询与该属性关联的部门信息。

方式三
使用嵌套结果映射association来处理重复的联合结果的子集封装联表查询数据(去除重复数据)

User user = userMapper.selectByPrimaryKeyWithDept2(1L);
System.out.println(user);
<resultMap id="BaseResultMapWithDept2" type="cn.hx.mybatis.entity.User">
        <id property="userId" column="user_id" jdbcType="BIGINT"/>
        <result property="username" column="username" jdbcType="VARCHAR"/>
        <result property="password" column="password" jdbcType="VARCHAR"/>
        <result property="salt" column="salt" jdbcType="VARCHAR"/>
        <result property="email" column="email" jdbcType="VARCHAR"/>
        <result property="mobile" column="mobile" jdbcType="VARCHAR"/>
        <result property="status" column="status" jdbcType="TINYINT"/>
        <result property="deptId" column="dept_id" jdbcType="BIGINT"/>
        <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
        <association property="dept" javaType="cn.hx.mybatis.entity.Dept">
            <id property="deptId" column="dept_id"></id>
            <result property="parentId" column="parent_id"></result>
            <result property="name" column="name"></result>
            <result property="orderNum" column="order_num"></result>
            <result property="delFlag" column="del_flag"></result>
        </association>
    </resultMap>

<select id="selectByPrimaryKeyWithDept2" parameterType="java.lang.Long" resultMap="BaseResultMapWithDept2">
        select user_id,
               username,
               password,
               salt,
               email,
               mobile,
               status,
               u.dept_id,
               create_time,
               parent_id,
               name,
               order_num,
               del_flag
        from sys_user u
                 left join sys_dept d on u.dept_id = d.dept_id
        where user_id = #{userId,jdbcType=BIGINT}
    </select>

< association property=“dept” javaType=“cn.hx.mybatis.entity.Dept”>
在这个例子中,关联属性 “dept” 的类型是 “cn.hx.mybatis.entity.Dept”,它与当前实体相关联。

这个关联属性可以用于从当前实体中获取相关的 “Dept” 实体,或者将相关的 “Dept” 实体设置为当前实体。它表示当前实体与 “Dept” 实体之间的一对一或多对一关系。

举个例子,假设有一个 “Employee” 实体和一个 “Dept” 实体,你可以使用这个关联属性将员工与部门关联起来。通过 “dept” 属性可以获取员工所在的部门,或者使用 “dept” 属性设置员工所在的部门。

总结

asssociation定义关联对象的封装规则
select:表明当前属性是调用指定的方法查出的结果
column:指定将那一列的值传给这个方法
#{}是使用占位符?(动态SQL)的方式编译和发送SQL;好处:防止SQL注入(推荐)
注意:使用#{}不能生成表名和字段名,所以在字段和表名处,必须使用${}

一对多级联查询

实体类

public class Dept{
private List<User> list;
    private Long deptId;
    private Long parentId;
    private String name;
    private Integer orderNum;
    private Integer delFlag;
}

public class User{
	private Dept dept;
    private Long userId;
    private String username;
    private String password;
    private String salt;
    private String email;
    private String mobile;
    private Integer status;
    private Long deptId;
    private Date createTime;
}

方式一
根据部门id查有多少用户

Dept dept = deptMapper.selectByPrimaryKey(2L);
dept.setList(userMapper.getByIdUser(dept.getDeptId()));
System.out.println(dept);

<resultMap id="BaseResultMap" type="cn.hx.mybatis.entity.Dept">
            <id property="deptId" column="dept_id" jdbcType="BIGINT"/>
            <result property="parentId" column="parent_id" jdbcType="BIGINT"/>
            <result property="name" column="name" jdbcType="VARCHAR"/>
            <result property="orderNum" column="order_num" jdbcType="INTEGER"/>
            <result property="delFlag" column="del_flag" jdbcType="TINYINT"/>
    </resultMap>

<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List" />
        from sys_dept
        where  dept_id = #{deptId,jdbcType=BIGINT} 
    </select>

方式二
嵌套查询,通过执行另一个SQL映射语句来返回预期的复杂类型

Dept dept = deptMapper.selectByPrimaryKeyWithUser(2L);
System.out.println(dept);

<resultMap id="BaseResultMapWithUser" type="cn.hx.mybatis.entity.Dept">
        <id property="deptId" column="dept_id" jdbcType="BIGINT"/>
        <result property="parentId" column="parent_id" jdbcType="BIGINT"/>
        <result property="name" column="name" jdbcType="VARCHAR"/>
        <result property="orderNum" column="order_num" jdbcType="INTEGER"/>
        <result property="delFlag" column="del_flag" jdbcType="TINYINT"/>
        <collection property="list" column="dept_id" select="cn.hx.mybatis.mapper.UserMapper.getByIdUser"/>
    </resultMap>

<select id="selectByPrimaryKeyWithUser" parameterType="java.lang.Long" resultMap="BaseResultMapWithUser" >
        select
        <include refid="Base_Column_List" />
        from sys_dept
        where  dept_id = #{deptId,jdbcType=BIGINT}
    </select>

< collection property=“list” column=“dept_id” select=“cn.hx.mybatis.mapper.UserMapper.getByIdUser”/>这段代码的作用是在查询某个实体对象时,同时查询该实体对象关联的用户列表,并将用户列表映射到实体对象的"list"集合属性中。这样,通过一次查询操作,就可以获取到实体对象及其关联的用户列表,简化了多次查询的过程。
具体解释如下:

  • < collection>标签用于配置关联映射中的集合属性
  • property=“list"表示要将查询结果映射到的目标对象中的集合属性名为"list”。
  • column=“dept_id"表示关联的列名为"dept_id”,即通过该列与目标对象进行关联。
  • select="cn.hx.mybatis.mapper.UserMapper.getByIdUser"表示通过调用"cn.hx.mybatis.mapper.UserMapper"接口中的"getByIdUser"方法来查询与该属性关联的用户列表。

方式三
嵌套结果:使用嵌套结果映射来处理重复的联合结果子集


<resultMap id="BaseResultMapWithUserWithUser2" type="cn.hx.mybatis.entity.Dept">
        <id property="deptId" column="dept_id" jdbcType="BIGINT"/>
        <result property="parentId" column="parent_id" jdbcType="BIGINT"/>
        <result property="name" column="name" jdbcType="VARCHAR"/>
        <result property="orderNum" column="order_num" jdbcType="INTEGER"/>
        <result property="delFlag" column="del_flag" jdbcType="TINYINT"/>
        <collection property="list" ofType="cn.hx.mybatis.entity.User">
            <id property="userId" column="user_id"></id>
            <result property="username" column="username"></result>
            <result property="password" column="password"></result>
            <result property="salt" column="salt"></result>
            <result property="email" column="email"></result>
            <result property="mobile" column="mobile"></result>
            <result property="status" column="status"></result>
            <result property="createTime" column="create_time"></result>
        </collection>
    </resultMap>

<select id="selectByPrimaryKeyWithUser2" parameterType="java.lang.Long" resultMap="BaseResultMapWithUserWithUser2">
        select d.dept_id,
               parent_id,
               name,
               order_num,
               del_flag,
               user_id,
               username,
               password,
               salt,
               email,
               mobile,
               status,
               create_time
        from sys_dept d
                 left join sys_user u on d.dept_id = u.dept_id
        where d.dept_id = #{deptId,jdbcType=BIGINT}
    </select>

< collection property=“list” ofType=“cn.hx.mybatis.entity.User”>这段代码的作用是在查询某个实体对象时,同时查询该实体对象关联的用户列表,并将用户列表映射到实体对象的"list"集合属性中。通过配置ofType属性,可以指定集合属性的元素类型,确保集合中的元素对象都是指定的类型。
具体解释如下:

  • < collection>标签用于配置关联映射中的集合属性
  • property=“list"表示要将查询结果映射到的目标对象中的集合属性名为"list”。
  • ofType=“cn.hx.mybatis.entity.User"表示集合属性的元素类型是"cn.hx.mybatis.entity.User”,即集合中的元素对象都是"cn.hx.mybatis.entity.User"类型的实例。

总结

cokkection定义关联集合类型的属性的封装规则
ofType:指定集合元素的类型
在mybatis中关联关系常用如下
一对一 association javaType
一对多 collection ofType

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
MyBatis级联查询是指在查询操作中,通过一次查询关联的多个表格,并将结果映射到一个复杂的对象中。通常情况下,关联查询需要多次查询数据库并手动组装结果,而级联查询则通过MyBatis的特性来自动完成这个过程。 在MyBatis中,通过`<association>`元素处理一对一级联关系。例如,我们有两个表格`orders`和`users`,其中`orders`表格中有一个`user_id`字段,指向`users`表格中的`id`字段。我们可以通过以下方式进行一对一级联查询: ```xml <!-- 定义resultMap --> <resultMap id="orderResultMap" type="Order"> <id property="id" column="id"/> <result property="orderNo" column="order_no"/> <result property="userId" column="user_id"/> <!-- 一对一级联查询 --> <association property="user" column="user_id" select="com.example.mapper.UserMapper.selectById"/> </resultMap> <!-- 定义select语句 --> <select id="selectOrder" resultMap="orderResultMap"> select * from orders where id = #{id} </select> ``` 在上面的例子中,我们定义了一个`orderResultMap`的`resultMap`,其中通过`<association>`元素定义了一对一级联查询。`<association>`元素的`property`属性指定了要级联的属性名,`column`属性指定了关联的字段名,`select`属性指定了要执行的查询语句。 需要注意的是,在`<association>`元素中,我们可以通过`select`属性指定要执行的查询语句,也可以通过`resultMap`属性指定要使用的`resultMap`。如果使用`select`属性,MyBatis会自动执行查询语句并将结果映射到对应的属性中;如果使用`resultMap`属性,MyBatis会使用指定的`resultMap`进行映射。 除了一对一级联查询MyBatis还支持一对多和多对多级联查询,分别通过`<collection>`和`<association>`元素实现。具体用法可以参考MyBatis官方文档。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值