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

  • 但,仅对变更的 address 实体执行了 update 语句;
  • 3.4.2. 只更新变更字段只更新变更字段,是指只更新实体类中有变化的字段,而不是全部字段 。为了实现按需更新,需要在实体类中使用@DynamicUpdate注解,表示只更新有变化的字段 。
    实体代码见:
    @Entity@Table(name = "order_info")@DynamicUpdatepublic class Order{// 其他忽略}测试代码如下:
    Order order = this.orderRepository.findById(this.order.getId()).get();order.setUserId(RandomUtils.nextLong()); // 仅更新 user idSystem.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: update order_info set user_id=? where id=?如果移除 @DynamicUpdate 注解,控制台输出如下:
    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: update order_info set address_id=?, pay_id=?, status=?, total_price=?, total_selling_price=?, user_id=? where id=?对比输出可知:使用@DynamicUpdate注解后,当修改实体类中的某个字段时,JPA会自动将该字段标记为“脏数据”,并只更新标记为“脏数据”的字段,这样可以减少数据库的IO操作,提高更新效率 。
    4. 小节本章从 DDD 聚合生命周期讲起,当我们面对一组高内聚对象时,如何更好的对这一对象组进行维护 。
    从高内聚对象组视角需要支持:
    1. 对象间的组合关系;
    2. 对象间的继承关系;
    从系统性能角度需要支持:
    1. 延迟加载:只有在使用时才触发实体加载;
    2. 按需更新:只对状态变更实体或字段进行更新;
    JPA 与 DDD 的==聚合写== 是绝配,但在 “读” 场景 往往会引发各种性能问题 。这也是很多公司弃用 JPA 而选择 MyBatis 的主要原因,就其本质并不是框架的错,而是将框架用在了错误的场景 。
    对于 Command 和 Query 分离架构,最佳组合是:
    1. Command 侧以 DDD 和 JPA 为核心,享受面向对象强大设计力,享受 JPA 所带来的便利性,从而解放双手,提升开发效率;
    2. Query 侧以 DTO 和 MyBatis 为核心,享受 MyBatis 对 SQL 强大控制力,更好的压榨 MySQL 性能,从而降低成本;




    推荐阅读