解密DDD:高内聚对象组的维护之道( 六 )

3.3.2. 延迟加载延迟加载是指在进行数据库查询时,并不会立即查询关联表数据,而是要等到使用时才会去查,这样可以避免不必要的数据库查询,提高查询效率 。
延迟加载又分为两种情况:

  1. 表间的延迟加载:在表关联情况下,进行数据库查询时,并不会立即查询关联表,而是要等到使用时才会去查数据库;
  2. 表中属性的延迟加载:比如大型字段blob,需要等到使用时才加载,这样可以避免不必要的数据库查询,提高查询效率;
在此,重点介绍表间关联的延迟加载:
实体代码如下所示:
@Entity@Table(name = "order_info")public class Order{@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)@JoinColumn(name = "order_id")private List<OrderItem> orderItems = new ArrayList<>();@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)private Pay pay;@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)private Address address;// 忽略其他字段和方法}查询代码如下:
Order order = this.orderRepository.findById(this.order.getId()).get();Assertions.assertNotNull(order);System.out.println("访问 item");Assertions.assertEquals(3, order.getOrderItems().size());System.out.println("访问 address");Assertions.assertNotNull(order.getAddress().getDetail());System.out.println("访问 pay");Assertions.assertNotNull(order.getPay().getPrice());控制台输出如下:
Hibernate: select order0_.id as id1_3_0_, order0_.address_id as address_6_3_0_, order0_.pay_id as pay_id7_3_0_, order0_.status as status2_3_0_, order0_.total_price as total_pr3_3_0_, order0_.total_selling_price as total_se4_3_0_, order0_.user_id as user_id5_3_0_ from order_info order0_ where order0_.id=?访问 itemHibernate: select orderitems0_.order_id as order_id6_4_0_, orderitems0_.id as id1_4_0_, orderitems0_.id as id1_4_1_, orderitems0_.price as price2_4_1_, orderitems0_.product_id as product_3_4_1_, orderitems0_.quantity as quantity4_4_1_, orderitems0_.selling_price as selling_5_4_1_ from order_item orderitems0_ where orderitems0_.order_id=?访问 addressHibernate: select address0_.id as id1_2_0_, address0_.detail as detail2_2_0_ from address address0_ where address0_.id=?访问 payHibernate: select pay0_.id as id1_5_0_, pay0_.price as price2_5_0_ from pay_info pay0_ where pay0_.id=?从日志输出可知,关联实体只有在属性被访问时才会触发自动加载 。
延迟加载在聚合更新时极为重要,面对一个大聚合,每次修改只会涉及少量相关联的实体,由于延迟加载机制的保障,对于那些没有必要访问的实体并不会执行实际的加载操作,从而大幅提升性能 。
3.4. 按需更新简单理解按需更新,就是只有在有必要时才会对数据进行更新 。
按需更新可以分为两个场景:
  1. 只更新变更实体:在保存一组对象时,只对状态发生变化的实体进行更新;
  2. 只更新变更字段:保存一个实体时,只对状态发生变化的字段进行更新;
3.4.1. 只更新变更实体在数据保存时,JPA 会自动识别发生变更的实体,仅对变更实体执行 update 语句 。
测试代码如下:
Order order = this.orderRepository.findById(this.order.getId()).get();order.getOrderItems().size(); // 获取未更新order.getPay().getPrice(); // 获取未更新order.getAddress().setDetail("新地址"); // 获取并更新System.out.println("更新数据");this.orderRepository.save(order);控制台输出如下:
Hibernate: select order0_.id as id1_3_0_, order0_.address_id as address_6_3_0_, order0_.pay_id as pay_id7_3_0_, order0_.status as status2_3_0_, order0_.total_price as total_pr3_3_0_, order0_.total_selling_price as total_se4_3_0_, order0_.user_id as user_id5_3_0_ from order_info order0_ where order0_.id=?Hibernate: select orderitems0_.order_id as order_id6_4_0_, orderitems0_.id as id1_4_0_, orderitems0_.id as id1_4_1_, orderitems0_.price as price2_4_1_, orderitems0_.product_id as product_3_4_1_, orderitems0_.quantity as quantity4_4_1_, orderitems0_.selling_price as selling_5_4_1_ from order_item orderitems0_ where orderitems0_.order_id=?Hibernate: select pay0_.id as id1_5_0_, pay0_.price as price2_5_0_ from pay_info pay0_ where pay0_.id=?Hibernate: select address0_.id as id1_2_0_, address0_.detail as detail2_2_0_ from address address0_ where address0_.id=?更新数据Hibernate: update address set detail=? where id=?从日志输出可见:
  1. 对聚合中 的实体进行了加载操作;


    推荐阅读