想用好 DDD 必须先过 Spring Data 这关( 三 )


单元测试 , 具体如下:
@Test void createOrder() { // 创订单 , 将整个 Order 聚合根全部保存到数据库 , 包括 // 1. order // 2. orderItem // 3. orderAddress CreateOrderCommand command = createOrderCommand(10L); Order order = this.applicationService.createOrder(command); Assertions.assertNotNull(order.getId()); }
运行单元测试 , 打印以下 SQL:
// createOrder 方法中 repository.save(order) 产生的 SQL: // 插入 收货地址 Hibernate: insert into tb_order_address (detail) values (?) // 插入 order Hibernate: insert into tb_order (user_address_id, price, status, user_id) values (?, ?, ?, ?) // 插入 orderItem Hibernate: insert into tb_order_item (amount, price, product_id, product_name, status) values (?, ?, ?, ?, ?) Hibernate: insert into tb_order_item (amount, price, product_id, product_name, status) values (?, ?, ?, ?, ?) Hibernate: insert into tb_order_item (amount, price, product_id, product_name, status) values (?, ?, ?, ?, ?) Hibernate: insert into tb_order_item (amount, price, product_id, product_name, status) values (?, ?, ?, ?, ?) Hibernate: insert into tb_order_item (amount, price, product_id, product_name, status) values (?, ?, ?, ?, ?) // 将 order item 与 order 进行绑定(这步存在性能损耗 , 但是目前没有更好的解决方案) Hibernate: update tb_order_item set order_id=? where id=? Hibernate: update tb_order_item set order_id=? where id=? Hibernate: update tb_order_item set order_id=? where id=? Hibernate: update tb_order_item set order_id=? where id=? Hibernate: update tb_order_item set order_id=? where id=?
是否发现 Spring Data Jpa 的强大之处:核心逻辑全部内聚在 Order 类 , 在没有写任何数据层访问代码的前提下 , 一个 save 方法便可以将这组高内聚的对象保存到 DB 。
5.2. 修改地址
修改地址核心代码如下:
@Transactional(readOnly = false) public void modifyAddress(Long orderId, String address){ Optional orderOptional = repository.findById(orderId); if (orderOptional.isPresent()){ Order order = orderOptional.get(); order.modifyAddress(address); this.repository.save(order); } } // Order 实体上的方法 public void modifyAddress(String address){ if (this.address == null){ this.address = new OrderAddress(); } this.address.modify(address); } // OrderAddress 实体上的方法 public void modify(String address) { setDetail(address); }
首先 , 看一个添加地址的场景 , 生单时没有提供收货地址 , 生单后修改地址:
@Test void modifyAddress_add() { // 新订单不存储地址信息(没有 userAddress) Order order = null; { CreateOrderCommand command = createOrderCommand(20L); // 将收获地址设置为 null command.setUserAddress(null); order = this.applicationService.createOrder(command); Assertions.assertNotNull(order.getId()); } // 修改时 , 直接创建地址(插入新数据) String address = "新增地址"; // Lazy 加载 , 只加载 orderAddress // 修改后 , 只更新 OrderAddress this.applicationService.modifyAddress(order.getId(), address); Order orderInDB = this.repository.findById(order.getId()).get(); Assertions.assertEquals(address, orderInDB.getAddress().getDetail() ); }
运行单测可 , 控制台输出以下信息:
// createOrder 方法中 repository.save(order) 产生的 SQL: // 生单时没有地址 , 所以没有向 tb_order_address 插入数据 Hibernate: insert into tb_order (user_address_id, price, status, user_id) values (?, ?, ?, ?) Hibernate: insert into tb_order_item (amount, price, product_id, product_name, status) values (?, ?, ?, ?, ?) Hibernate: insert into tb_order_item (amount, price, product_id, product_name, status) values (?, ?, ?, ?, ?) Hibernate: insert into tb_order_item (amount, price, product_id, product_name, status) values (?, ?, ?, ?, ?) Hibernate: insert into tb_order_item (amount, price, product_id, product_name, status) values (?, ?, ?, ?, ?) Hibernate: insert into tb_order_item (amount, price, product_id, product_name, status) values (?, ?, ?, ?, ?) Hibernate: update tb_order_item set order_id=? where id=? Hibernate: update tb_order_item set order_id=? where id=? Hibernate: update tb_order_item set order_id=? where id=? Hibernate: update tb_order_item set order_id=? where id=? Hibernate: update tb_order_item set order_id=? where id=? // modifyAddress 方法中 repository.findById(orderId) 产生的 SQL // 从 DB 中加载数据 , 构建内存的 Order 对象 Hibernate: select order0_.id as id1_0_0_, order0_.user_address_id as user_add5_0_0_, order0_.price as price2_0_0_, order0_.status as status3_0_0_, order0_.user_id as user_id4_0_0_ from tb_order order0_ where order0_.id=? // modifyAddress 方法中 this.repository.save(order) 产生的 SQL // 为 Order 对象添加 orderAddress 后 , 自动向数据库添加数据 Hibernate: insert into tb_order_address (detail) values (?) // 更新 Order 的 user_address , 完成数据绑定 Hibernate: update tb_order set user_address_id=?, price=?, status=?, user_id=? where id=? // repository.findById(order.getId()) 产生的 SQL // 从 DB 中加载数据 , 构建内存的 Order 对象 , 进行结果检测 Hibernate: select order0_.id as id1_0_0_, order0_.user_address_id as user_add5_0_0_, order0_.price as price2_0_0_, order0_.status as status3_0_0_, order0_.user_id as user_id4_0_0_ from tb_order order0_ where order0_.id=?


推荐阅读