MyBatis最佳实践之——关联查询

我们在查询业务数据的时候经常会遇到关联查询的情况。
比如查询用户会关联设备(1对多),查询设备会关联用户(1对1)。

一个设备属于一个用户,这是一对一的关系:如下内容:

#设备表
CREATE TABLE `t_device` (
  `id` int NOT NULL,
  `sn` varchar(45) DEFAULT NULL,
  `u_id` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
#用户表
CREATE TABLE `t_user` (
  `uid` int NOT NULL,
  `name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
<select id="queryUserNested" resultMap="nestedMap">
    select
        t1.id,
        t1.sn,
        t2.uid,
        t2.name
    from
        t_device t1
    left join t_user t2 on t1.u_id = t2.uid
</select>

<resultMap id="nestedMap" type="com.lk.tool.bean.Device">
    <id property="id" column="id" jdbcType="INTEGER"/>
    <result property="sn" column="sn" jdbcType="VARCHAR"/>
    <association property="user" javaType="com.lk.tool.bean.User">
        <id column="uid" property="uid"/>
        <result column="name" property="name"/>
    </association>
</resultMap>

实体类

@Data
@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Device {
    private int id;
    private String sn;
    private User user;
}

@Data
@NoArgsConstructor
public class User {
    private int uid;
    private String name;
}

测试类:

@Test
void testAssociateQuery() throws IOException {
    InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
    SqlSession sqlSession = sqlSessionFactory.openSession();
    DeviceMapper deviceMapper = sqlSession.getMapper(DeviceMapper.class);
    List<Device> list = deviceMapper.queryUserNested();
    sqlSession.commit();
    sqlSession.close();
    list.forEach(entity->{
        System.out.println(entity);
    });
}

测试类执行结果:

Device(id=1, sn=CHYLL00001, user=User(uid=1, name=Emily))
Device(id=2, sn=CHYLL00002, user=User(uid=2, name=Chris))
Device(id=3, sn=CHYLL00003, user=User(uid=3, name=Eva))
Device(id=4, sn=CHYLL00004, user=User(uid=4, name=Spring))

一个用户可以拥有多个设备,这是一对多的关系,如下所示:

    <resultMap id="NestedDevice" type="user">
        <id property="uid" column="uid"/>
        <result property="name" column="name"/>
        <collection property="devices" ofType="device">
            <id property="id" column="id"/>
            <result property="sn" column="sn"/>
        </collection>
    </resultMap>
    
    <select id="queryUserNested" resultMap="NestedDevice">
        select
        t1.uid,
        t1.name,
        t2.id,
        t2.sn
        from t_user t1
        left join t_device t2 on t1.uid = t2.u_id
    </select>

执行结果:

User(uid=1, name=Emily, devices=[Device(id=5, sn=CHYLL00005, user=null), Device(id=1, sn=CHYLL00001, user=null)])
User(uid=2, name=Chris, devices=[Device(id=2, sn=CHYLL00002, user=null)])
User(uid=3, name=Eva, devices=[Device(id=3, sn=CHYLL00003, user=null)])
User(uid=4, name=Spring, devices=[Device(id=4, sn=CHYLL00004, user=null)])

关联(association)元素处理“有一个”类型的关系。 比如,在我们的示例中,一个博客有一个用户。关联结果映射和其它类型的映射工作方式差不多。 你需要指定目标属性名以及属性的javaType(很多时候 MyBatis 可以自己推断出来),在必要的情况下你还可以设置 JDBC 类型,如果你想覆盖获取结果值的过程,还可以设置类型处理器。
关联的不同之处是,你需要告诉 MyBatis 如何加载关联。MyBatis 有两种不同的方式加载关联:

嵌套结果映射:使用嵌套的结果映射来处理连接结果的重复子集。
嵌套 Select 查询:通过执行另外一个 SQL 映射语句来加载期望的复杂类型。

延迟加载

在settings标签里设置:

<!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认false -->
<setting name="lazyLoadingEnabled" value="true"/>
<!--当开启时,任何方法的调用都会加载该对象的所有属性。默认false,可通过select标签的
fetchType来覆盖-->
<setting name="aggressiveLazyLoading" value="false"/>

lazyLoadingEnabled 决定来是否延迟加载(默认false)
aggressiveLazyLoading决定了是不是对象的所有方法都会触发查询。
启用延迟加载后,当使用到被关联的属性时才会执行查询,否则不会执行子查询。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值