Spring笔记(08) Mybatis 延迟加载 懒加载案例

Java 程序代码与数据库交互越低越好,避免浪费资源。Mybatis提供了一种延迟加载机制,类似懒加载,在此之前,使用了这么久的 Mybatis,第一次了解到这个概念。

然后仔细学了一遍,怎么说呢,在实际项目中使用还是有一些限制。首先就是麻烦,本来一条sql能完成的查询,要分开写。其次联查两个表倒是可以用,当联查三个表时,说实话还没搞懂怎么用。最后我觉得这是个伪需求,查出来的字段一定是需要用的,不然为什么要查它。

但是不妨碍学习。本篇通过实际案例的方式来理解和学习这种使用方法。

现在有两个表,对应的实体类如下:

客户(Customer)

public class Customer {
    private Long id;
    private String name;
    private List<Order> orders;
}

订单(Order)

public class Order {
    private Long id;
    private String name;
    private Customer customer;
}

这两者是一对多的关系,按照这种模型,数据库建表,t_customer 为主表,t_order 为从表。t_customer 的主键是 t_order 的外键。

然后分别建了两个对应表

CREATE TABLE `t_customer` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

CREATE TABLE `t_order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(11) DEFAULT NULL,
  `cid` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `cid` (`cid`),
  CONSTRAINT `t_order_ibfk_1` FOREIGN KEY (`cid`) REFERENCES `t_customer` (`id`)
);

然后分别加了数据进去

然后我创建了两组 mapper,分别是 OrderRepository、OrderRepository.xml

public interface OrderRepository {
    public Order findById(Long id);
}
<?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.guozh.lazy.OrderRepository">

    <resultMap id="getOrderByIdMap" type="com.guozh.lazy.Order">
        <id property="id" column="id"></id>
        <result property="name" column="name"></result>
        <association property="customer" javaType="com.guozh.lazy.Customer" select="com.guozh.lazy.CustomerRepository.findById" column="cid">
        </association>
    </resultMap>

    <select id="findById" parameterType="java.lang.Long" resultMap="getOrderByIdMap">
        select * from t_order where id = #{id};
    </select>

</mapper>

CustomerRepository、CustomerRepository.xml

public interface CustomerRepository {
    public Customer findById(Long id);
}
<?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.guozh.lazy.CustomerRepository">

    <select id="findById" parameterType="java.lang.Long" resultType="com.guozh.lazy.Customer">
        select * from t_customer where id = #{id};
    </select>

</mapper>

然后在 config 中注册这两个 mapper.xml

<mappers>
        <mapper resource="com/guozh/lazy/OrderRepository.xml"></mapper>
        <mapper resource="com/guozh/lazy/CustomerRepository.xml"></mapper>
    </mappers>

因为我将 xml 放到 java 代码包下,并不是 resources ,所以还需要在 pom文件配置如下代码,不然会找不到 mapper.xml文件的

 <resources>
      <resource>
        <directory>src/main/java</directory>
        <includes>
          <include>**/*.xml</include>
        </includes>
      </resource>
    </resources>

然后在全局配置文件中配上打印 SQL 语句 ,不然控制台不知道java代码和数据库交互查询了几次。

 <settings>
        <!-- 打印查询语句 -->
        <setting name="logImpl" value="STDOUT_LOGGING" />
    </settings>

在运行如下代码,进行测试

InputStream inputStream = App.class.getClassLoader().getResourceAsStream("config.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        OrderRepository orderRepository = sqlSession.getMapper(OrderRepository.class);
        Order order = orderRepository.findById(1L);
        System.out.println(order.getName());

从图中可以看到,确实执行查询了两条 SQL ,虽然我使用的是第一次查询的数据,也就是只要查询 Order表就行。现在开启延迟加载,这样如果没使用 Consumer 表中的数据,则不会去查询。

   <!--设置 settings -->
    <settings>   
        <!--打开延迟加载的开关 -->
        <setting name="lazyLoadingEnabled" value="true" />
    </settings>

测试结果图如下

从上图可看出,查询次数已经变成只查询 t_order 表。现在修改测试代码,使用第二个表 t_consumer 中的数据

System.out.println(order.getCustomer().getName());

从上图结果可以看出,查询两次。

正如我前面所说呢,这功能实际使用中很鸡肋,看不到使用场景。毕竟,如果不需要某个数据,查询时就不当作查询字段了。或者直接联表查询也行,联表时也只会执行一次查询。

select o.id oid,o.name oname,c.id cid ,c.name cname from t_order o
join t_customer c on o.cid = c.id where o.id = 1;

以上代码笔记内容来自付费专栏:案例上手 Spring 全家桶

PS:并没有透露关键内容,纯粹是零碎笔记。如果侵犯版权,请联系我。

 

本文由老郭种树原创,转载请注明:https://guozh.net/spring-mybatis-lazy-load/

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注