mybatis 多层(三层)嵌套查询

一、java 实体描述

/**
 * <p>
 * 家庭表
 * </p>
 *
 * @author lohas
 */
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("t_family_info")
@ApiModel(value = "FamilyInfoEntity对象", description = "家庭表")
public class FamilyInfoEntity extends Model {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键")
    @TableId(value = "id", type = IdType.INPUT)
    private String id;

    @ApiModelProperty(value = "家庭名称")
    private String familyName;

    @ApiModelProperty(value = "家庭头像url")
    private String headUrl;

    @ApiModelProperty(value = "国家")
    private String country;

    @ApiModelProperty(value = "城市")
    private String city;

    @ApiModelProperty(value = "地址")
    private String address;

    @ApiModelProperty(value = "经度")
    private BigDecimal longitude;

    @ApiModelProperty(value = "纬度")
    private BigDecimal latitude;

    @ApiModelProperty(value = "租户ID")
    private String tenantId;

    @ApiModelProperty(value = "是否删除(0:正常;低于0的数字:已删除)")
    private String deleteFlag;

    @ApiModelProperty(value = "创建人ID")
    private String creatorId;

    @ApiModelProperty(value = "创建时间")
    @JsonDeserialize(using = LocalDateTimeSerializerConfig.LocalDateTimeDeserializer.class)
    @JsonSerialize(using = LocalDateTimeSerializerConfig.LocalDateTimeSerializer.class)
    private LocalDateTime createTime;

    @ApiModelProperty(value = "更新人ID")
    private String updateId;

    @ApiModelProperty(value = "更新时间")
    @JsonDeserialize(using = LocalDateTimeSerializerConfig.LocalDateTimeDeserializer.class)
    @JsonSerialize(using = LocalDateTimeSerializerConfig.LocalDateTimeSerializer.class)
    private LocalDateTime updateTime;

}
/**
 * @author lohas
 * @description
 */
@Data
@ApiModel(value = "RoomDeviceInfoVo对象", description = "房间设备信息实体")
public class RoomDeviceInfoVo implements Serializable {

    @ApiModelProperty(value = "房间id")
    private String roomId;

    @ApiModelProperty(value = "房间名称")
    private String roomName;

    @ApiModelProperty(value = "设备数量")
    private Integer deviceNum;

    @ApiModelProperty(value = "设备信息列表")
    private List<String> deviceIds;
}

/**
 * @author lohas
 * @description
 */
@Data
@ApiModel(value = "FamilyRoomInfoVo对象", description = "家庭房间信息对象实例")
public class FamilyRoomInfoVo extends FamilyInfoEntity {

    @ApiModelProperty(value = "房间设备信息列表")
    private List<RoomDeviceInfoVo> roomDeviceInfoVoList;
}

二、mybatis 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.lohas.mapper.FamilyInfoMapper">

    <select id="getFamilyRoomInfoVoByUserId" resultMap="familyMap">
		SELECT *
		FROM (
             SELECT tfi.*,
                    trf."id"      AS r_room_id,  --要加上r因为columnPrefix="r_"(如果字段唯一,可以不加)
                    trf.room_name AS r_room_name, --要加上r因为columnPrefix="r_"
                    trd.device_id AS r_d_device_id --要加上r因为columnPrefix="r_",加上d因为columnPrefix="d_"
             FROM t_user_family tuf
                      LEFT JOIN t_family_info tfi ON tfi.ID = tuf.family_id
                      LEFT JOIN t_family_room tfr ON tuf.family_id = tfr.family_id
                      LEFT JOIN t_room_info trf ON tfr.room_id = trf.ID
                      LEFT JOIN t_room_device trd ON tfr.room_id = trd.room_id
             WHERE tuf.user_id = #{userId}
             ORDER BY tfi.create_time DESC
         ) AS fr,
         (
             SELECT trf."id"             AS r_room_id,  --要加上r因为columnPrefix="r_"
                    COUNT(trd.device_id) AS r_device_num  --要加上r因为columnPrefix="r_"
             FROM t_user_family tuf
                      LEFT JOIN t_family_info tfi ON tfi.ID = tuf.family_id
                      LEFT JOIN t_family_room tfr ON tuf.family_id = tfr.family_id
                      LEFT JOIN t_room_info trf ON tfr.room_id = trf.
                 ID
                      LEFT JOIN t_room_device trd ON tfr.room_id = trd.room_id
             WHERE tuf.user_id = #{userId}
             GROUP BY trf."id"
         ) AS rd
		WHERE fr.r_room_id = rd.r_room_id
	</select>

	<resultMap id="familyMap" type="com.lohas.vo.FamilyRoomInfoVo">
		<!-- 一层: 家庭信息-->
		<id column="id" jdbcType="VARCHAR" property="id"/>
		<result column="family_name" jdbcType="VARCHAR" property="familyName"/>
		<result column="head_url" jdbcType="VARCHAR" property="headUrl"/>
		<result column="country" jdbcType="VARCHAR" property="country"/>
		<result column="city" jdbcType="VARCHAR" property="city"/>
		<result column="address" jdbcType="VARCHAR" property="address"/>
		<result column="longitude" jdbcType="NUMERIC" property="longitude"/>
		<result column="latitude" jdbcType="NUMERIC" property="latitude"/>
		<result column="delete_flag" jdbcType="CHAR" property="deleteFlag"/>
		<result column="creator_id" jdbcType="VARCHAR" property="creatorId"/>
		<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
		<result column="update_id" jdbcType="VARCHAR" property="updateId"/>
		<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
		<result column="tenant_id" jdbcType="VARCHAR" property="tenantId"/>
		<!-- 如果字段唯一,可以不加columnPrefix="r_"-->
		<collection property="roomDeviceInfoVoList" columnPrefix="r_" resultMap="roomMap"/>
	</resultMap>

	<resultMap id="roomMap" type="com.lohas.vo.RoomDeviceInfoVo">
		<!-- 二层: 房间信息-->
		<result column="room_id" jdbcType="VARCHAR" property="roomId"/>
		<result column="room_name" jdbcType="VARCHAR" property="roomName"/>
		<result column="device_num" jdbcType="VARCHAR" property="deviceNum"/>
		<!-- 如果字段唯一,可以不加columnPrefix="d_"-->
		<collection property="deviceIds" columnPrefix="d_" resultMap="deviceMap"/>
	</resultMap>

	<resultMap id="deviceMap" type="string">
		<!-- 三层: 设备信息-->
		<result column="device_id" jdbcType="VARCHAR"/>
	</resultMap>

</mapper>

三、调用方法

public interface FamilyInfoMapper extends BaseMapper<FamilyInfoEntity> {

	List<FamilyRoomInfoVo> getFamilyRoomInfoVoByUserId(@Param("userId") String userId);
   
}

四、注意总结

如果你的字段唯一,columnPrefix="r_" 和 columnPrefix="d_",可以不加,如果你加上了columnPrefix记得在字段上拼接上,否则查询不出数据,拼接要有前后顺序拼接例如:

<collection property="roomDeviceInfoVoList" columnPrefix="r_" resultMap="roomMap"/>

<collection property="deviceIds" columnPrefix="d_" resultMap="deviceMap"/>

r_d_device_id(要加上r因为roomMap columnPrefix="r_",加上d因为deviceMap columnPrefix="d_")

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: MyBatis的Collection多层嵌套可以通过使用<collection>标签来实现。每一层都可以使用<collection>标签,并且可以通过select属性指定查询语句。例如: ``` <resultMap id="nestedResultMap" type="Parent"> <id property="id" column="id"/> <result property="name" column="name"/> <collection property="children" ofType="Child"> <id property="id" column="child_id"/> <result property="name" column="child_name"/> <collection property="grandchildren" ofType="Grandchild"> <id property="id" column="grandchild_id"/> <result property="name" column="grandchild_name"/> </collection> </collection> </resultMap> <select id="selectNested" resultMap="nestedResultMap"> SELECT * FROM parent LEFT JOIN child ON parent.id = child.parent_id LEFT JOIN grandchild ON child.id = grandchild.child_id </select> ``` 希望这个回答对您有帮助! ### 回答2: Mybatis是一个Java持久层框架,它支持ORM方式,通过XML或注解的配置方式,将关系数据库中的数据映射到Java对象中,同时提供了灵活的SQL编写方式,使得开发者可以灵活地进行自定义SQL操作。 在Mybatis中,Collection多层嵌套是指在一个实体类中,如果有某个属性对应的数据库列是一个合或数组类型,则可以通过Mybatis的Collection标签来实现该属性的映射。同样,如果这个合或数组中的元素也是一个实体对象,则可以通过在Collection标签中再次使用Mybatis的Nested-select标签来实现多层嵌套的映射。 例如,一个学生有多个选课记录,每个选课记录又包含一个课程和教师信息。如果我们要把这些信息映射到Java对象中,则可以定义一个Student实体对象,其中包含一个名为courses的合属性,courses中的元素是一个Course对象,Course对象又包含一个Teacher对象。 在映射配置文件中,我们可以使用Collection标签来映射这个courses属性,同时可以在Collection标签中再次使用Nested-select标签来映射Course对象中的teacher属性。具体的配置方式如下: ``` <resultMap id="studentMap" type="Student"> <result property="id" column="id" /> <result property="name" column="name" /> <collection property="courses" ofType="Course"> <result property="id" column="course_id" /> <result property="name" column="course_name" /> <nestedSelect select="selectTeacherByCourseId" resultMap="teacherMap" /> </collection> </resultMap> <resultMap id="teacherMap" type="Teacher"> <result property="id" column="teacher_id" /> <result property="name" column="teacher_name" /> </resultMap> <select id="selectStudentById" resultMap="studentMap"> select * from student where id = #{id} </select> <select id="selectTeacherByCourseId" resultMap="teacherMap"> select * from teacher where id in ( select teacher_id from course_teacher where course_id = #{id} ) </select> ``` 通过这种方式,我们就可以轻松地实现多层嵌套的属性映射,使得实体类中的属性可以与数据库中的多个表关联,提高了数据查询和操作的灵活性。 ### 回答3: MyBatis是一个流行的Java持久化框架,在操作数据库时提供了方便和灵活性。当我们需要操作具有多层嵌套结构的数据时,MyBatis的collection标签就派上了用场。 collection标签有以下属性: - property:指定属性名称; - ofType:指定合元素的类型; - select:指定关联查询的SQL语句; - resultMap:指定结果映射的ID; - javaType:指定Java类型; - column:指定表中的列名。 由于MyBatis的collection标签有那么多属性,所以有时可能会感到混乱。在多层嵌套结构中,我们需要按照我们的需求设置标签中的属性。 假设我们有一个宠物店应用程序,其中包含如下实体类: ```java public class Pet { private Long id; private String name; private String breed; private List<Toy> toys; // 省略getter和setter方法 } public class Toy { private Long id; private String name; // 省略getter和setter方法 } ``` 我们需要从数据库中获取所有宠物和每个宠物所拥有的玩具。在这种情况下,我们需要使用collection标签。 ```xml <!-- 查询所有的宠物和联合查询玩具 --> <select id="getAllPets" resultMap="petResultMap"> SELECT p.id, p.name, p.breed, t.id AS toy_id, t.name AS toy_name FROM pet p LEFT JOIN toy t ON t.pet_id = p.id </select> <!-- 配置resultMap --> <resultMap id="petResultMap" type="Pet"> <id property="id" column="id"/> <result property="name" column="name"/> <result property="breed" column="breed"/> <!-- 用collection标签映射pet有many的toy合 --> <collection property="toys" ofType="Toy" resultMap="toyResultMap"/> </resultMap> <resultMap id="toyResultMap" type="Toy"> <id property="id" column="toy_id"/> <result property="name" column="toy_name"/> </resultMap> ``` 在上面的示例中,我们定义了两个resultMap来映射查询结果。 petResultMap将查询到的数据映射到Pet实体类中,并使用collection标签映射每个Pet对象的toys属性为一个玩具列表。```ofType="Toy"```属性告诉MyBatis将toys属性映射为Toy对象的列表。Collection标签中resultMap属性设置为```toyResultMap```告诉MyBatis将查询结果映射到Toy对象上。 以上就是MyBatis collection多层嵌套的简单介绍。深入理解和熟练掌握这个标签不仅可以让我们更好地利用MyBatis操作数据,而且可以提高我们的编码效率。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值