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/