【Java】Mybatis使用Collection属性

前言

这篇文章实现一下不使用left join等连接关键字来实现Mybatis的联表查询功能。包括json类型数据映射到Java实体类中。

库表

父表db1_json

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zIuG3a9a-1689752532289)(C:\Users\Admin\AppData\Roaming\marktext\images\2023-07-19-15-19-09-image.png)]

子表db1_json_attach,子表parent_id对应副本的id

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LMlft32m-1689752532290)(C:\Users\Admin\AppData\Roaming\marktext\images\2023-07-19-15-19-47-image.png)]

实体类

新建Db1JsonDTO数据传递对象实体。

@Data
public class Db1JsonDTO {
    //父表id
    private Long id;

    //父表信息
    private JSONObject info;

    //子表数据
    private List<Db1JsonAttach> attaches;
}

查看子表实体属性

@TableName(value ="db1_json_attach")
@Data
public class Db1JsonAttach implements Serializable {
    private Long parentId;

    @TableId(type = IdType.ID_WORKER)
    private Long id;

    @TableField(typeHandler = JacksonTypeHandler.class)
    private JSONObject info;

    private static final long serialVersionUID = 1L;
}

Mapper.xml

父xml处理,sql没什么好看的,看一下<resultMap>中各个属性吧。

<resultMap id="Db1JsonDTOResultMap" type="com.it.dto.Db1JsonDTO">
    <result column="info" property="info" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
  
    <collection property="attaches" column="{parentId = id}"
                select="com.it.mapper.Db1JsonAttachMapper.getAttachList"/>
</resultMap>
<select id="selectDb1JsonList" resultMap="Db1JsonDTOResultMap">
    select id,info from db1_json
</select>
  • id:自定义id,在SQL查询后使用resultMap属性并指定id返回。

  • type:返回字段对应的实体类,也可以是DTO,实体需要有Getter、Setter方法。

  • <result column:数据库中的字段名称。

  • <result property:与数据库字段对应的属性名。

  • <result typeHandler:对特殊类型进行处理,例如当前为json类型,指定将返回的结果进行转化后映射到实体属性中。

  • <collection property:父实体中的list集合数据,即为子实体类的集合。

  • <collection column:id字段赋值,将父id字段赋值给子id。

  • <collection select :指定子xmlSQL查询的方法id。

子xml处理

<resultMap id="BaseResultMap" type="com.it.entity.Db1JsonAttach">
        <id property="parentId" column="parent_id" jdbcType="BIGINT"/>
        <result property="id" column="id" jdbcType="BIGINT"/>
    <result property="info" column="info"  typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
</resultMap>


<select id="getAttachList" resultMap="BaseResultMap">
    select * from db1_json_attach where parent_id = #{parentId}
</select>

注:Mapper中不需要定义查询方法,只在XML中定义即可。

测试

看一下测试结果

[
  {
    "id": 1681557955655049218,
    "info": {
      "address": "洛杉矶",
      "name": "科比",
      "hobby": "直升机"
    },
    "attaches": [
      {
        "parentId": 1681557955655049218,
        "id": 1681557956250640385,
        "info": {
          "address": "洛杉矶",
          "name": "科比",
          "hobby": "直升机"
        }
      }
    ]
  },
  {
    "id": 1681558109766361089,
    "info": {
      "address": "美国",
      "name": "蔡徐坤",
      "hobby": "唱跳rap篮球"
    },
    "attaches": [
      {
        "parentId": 1681558109766361089,
        "id": 1681558109766361090,
        "info": {
          "address": "美国",
          "name": "蔡徐坤",
          "hobby": "唱跳rap篮球"
        }
      }
    ]
  },
  {
    "id": 1681558181665120257,
    "info": {
      "address": "理塘",
      "name": "丁真",
      "hobby": "测码"
    },
    "attaches": [
      {
        "parentId": 1681558181665120257,
        "id": 1681558181732229122,
        "info": {
          "address": "理塘",
          "name": "丁真",
          "hobby": "测码"
        }
      }
    ]
  }
]

总结

这个方式的联表查询用的不算太多,但是在一些特殊情况可以使用这种方式来完成查询子表的某一下数据集合。

如果对你有帮助请点个赞!

### MyBatis 中 `collection` 的使用方法及示例 MyBatis 提供了强大的功能用于处理复杂的关系映射,特别是针对一对多关系的场景。以下是有关 `collection` 属性的具体说明以及如何在 XML 文件中配置它的详细示例。 #### 1. `collection` 的基本概念 `collection` 主要用于解决 **一对多** 关系的映射问题。例如,一个部门 (`Department`) 可能对应多个员工 (`Employee`)。在这种情况下,可以在 `resultMap` 中定义一个 `collection` 节点来表示这种关联关系[^2]。 - `property`: 映射到实体类中的字段名。 - `ofType`: 集合中元素的类型。 - `column`: 数据库表中的列名,通常作为外键使用。 - `select|join`: 支持嵌套查询 (通过另一个 SQL 查询获取数据) 或联合查询 (在同一条 SQL 中完成). --- #### 2. 示例代码 ##### (1)数据库设计 假设有两张表:`t_dept` 和 `t_emp`,分别代表部门和员工的信息,并且存在外键关系 `t_emp.did -> t_dept.id`. ```sql CREATE TABLE t_dept ( id INT PRIMARY KEY, dept_name VARCHAR(50) ); CREATE TABLE t_emp ( eid INT PRIMARY KEY, emp_name VARCHAR(50), did INT, -- 外键指向 t_dept(id) FOREIGN KEY(did) REFERENCES t_dept(id) ); ``` --- ##### (2)Java 实体类 定义两个对应的实体类 `Dept` 和 `Emp`: ```java public class Dept { private Integer did; private String deptName; // 员工列表 private List<Emp> emps; // Getter and Setter methods... } public class Emp { private Integer eid; private String empName; // 所属部门ID(可选) private Integer did; // Getter and Setter methods... } ``` --- ##### (3)XML 配置文件 下面是一个完整的 `resultMap` 配置示例,展示如何使用 `collection` 来实现一对多映射: ```xml <resultMap id="deptEmpMap" type="Dept"> <!-- 部门基本信息 --> <id property="did" column="did"/> <result property="deptName" column="dept_name"/> <!-- 员工集合 --> <collection property="emps" <!-- 对应 Dept 类中的 emps 字段 --> ofType="Emp" <!-- 集合中每个元素的类型为 Emp --> column="{did=did}" <!-- 将当前部门 ID 传递给子查询 --> select="getEmployeesByDid"> <!-- 子查询方法名称 --> </collection> </resultMap> <!-- 获取某个部门及其下属员工 --> <select id="getDeptById" resultMap="deptEmpMap"> SELECT * FROM t_dept WHERE id = #{did}; </select> <!-- 子查询:根据部门 ID 获取所有员工 --> <select id="getEmployeesByDid" resultType="Emp"> SELECT * FROM t_emp WHERE did = #{did}; </select> ``` --- #### 3. 解析与注意事项 - 上述例子采用了 **嵌套查询** 的方式,即通过 `select` 属性调用另一个 SQL 方法来获取集合中的数据[^3]。 - 如果希望直接在一个 SQL 中完成联查,则可以改用 `join` 形式: ```xml <resultMap id="deptEmpJoinMap" type="Dept"> <id property="did" column="did"/> <result property="deptName" column="dept_name"/> <collection property="emps" ofType="Emp"> <id property="eid" column="eid"/> <result property="empName" column="emp_name"/> </collection> </resultMap> <select id="getDeptAndEmps" resultMap="deptEmpJoinMap"> SELECT d.*, e.eid, e.emp_name FROM t_dept d LEFT JOIN t_emp e ON d.id = e.did WHERE d.id = #{did}; </select> ``` - 在性能方面,推荐根据实际情况选择合适的策略。如果数据量较大,建议优先考虑嵌套查询配合延迟加载(`fetchType=lazy`)以减少内存占用。 --- #### 4. 测试接口 最后,在 Mapper 接口中定义相应的方法: ```java @Mapper public interface DeptMapper { Dept getDeptById(@Param("did") int did); // 使用嵌套查询或联查均可 } ``` --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值