DDD设计方法-3-仓储,封装持久化数据

前情提要:一共包含 如下六篇文章(篇幅精简,快速入门)

1、初识DDD
2、聚合、实体、值对象
3、仓储,封装持久化数据
4、端口和适配器
5、领域事件
6、领域服务,实现约定

DDD设计方法-3-仓储,封装持久化数据

  • 前言
  • 1、概念 什么是仓储?
  • 2、优缺点 为什么要用?
  • 3、和mapper到底什么区别?有关系吗?
  • 4、实例: 这里吧mapper 和 Repository 都写出来做个比较更直观一些
    • Mapper
      • 定义Mapper接口
      • 定义Mapper接口对应服务层
    • Repository
      • 定义仓储接口
      • 实现仓储接口
      • 使用仓储模式的服务层
  • 这里简单说下两者写法的区别和使用仓储模式的好处

前言

面向对象的设计中,持久化数据的管理和访问是一个关键问题。为了解决这一问题,领域驱动设计(DDD)引入了仓储(Repository)模式。本文将深入探讨仓储模式的概念、作用以及如何实现和使用它来封装持久化数据。

1、概念 什么是仓储?

仓储模式是一种用于管理和访问持久化数据的设计模式。( 可以理解为更高抽象层次的mapper )
它通过提供一个抽象层,将数据存储的细节隐藏起来,使得上层业务逻辑不必直接与数据库交互,从而实现数据访问的解耦合。

2、优缺点 为什么要用?

在这里插入图片描述

先说缺点:
如果你的项目使用crud就非常清晰明了的可以完成你当前的业务 ,那么你引入这层会使你的代码量增加,且基本上属于 事倍功半。
优点:

1、解耦:
将业务逻辑与数据访问分离,提高代码的可维护性和可测试性。
2、易于替换:
由于仓储接口与其实现分离,更换不同的持久化技术时无需修改业务代码。
3、统一访问:
通过仓储模式,可以对数据访问进行统一管理,方便集中控制和优化。

3、和mapper到底什么区别?有关系吗?

相同点 :
1、都是涉及到数据库操作,负责从数据源获取数据,并将数据保存到数据源。
2、解耦:都旨在解耦业务逻辑和数据访问逻辑。

不同点

抽象级别:仓储模式通常在更高的抽象级别上工作,提供的是领域对象的集合操作接口,而Mapper更专注于单个对象与数据库记录之间的映射。

职责范围:仓储模式不仅包括数据映射,还包括业务相关的查询和操作逻辑;而Mapper主要关注对象与数据库之间的映射和简单的CRUD操作。

使用场景:仓储模式更多地在领域驱动设计(DDD)中应用,强调领域对象和持久化的隔离;而Mapper模式更适合直接操作数据库的场景,特别是当使用ORM框架时。

上边说的比较官方 ,我这边白话文在表格中解释一下

关于数据映射操作

mapper 数据映射 做简单的 CRUD 的

仓储模式(Repository Pattern) 前一篇文章我们理解过聚合的概念,可以吧那个思路带入进来,这个是针对多表复杂业务的统一 CRUD的 其中包含业务处理 !

同时由于仓储模式的数据操作时和业务聚合在一起的,
所以会带来另一个优点就是可以隐藏持久化的细节,在更换数据库类型的时候无需大量修改service

4、实例: 这里吧mapper 和 Repository 都写出来做个比较更直观一些

Mapper

定义Mapper接口

public interface OrderMapper {void insertOrder(Order order);void updateOrder(Order order);void deleteOrderById(String orderId);Order selectOrderById(String orderId);// 其他与订单相关的CRUD操作
}

定义Mapper接口对应服务层

服务层A 既做订单的保存,又有删除。

public class OrderServiceWithMapperA {private final OrderMapper orderMapper;public OrderServiceWithMapper(OrderMapper orderMapper) {this.orderMapper = orderMapper;}public void createOrder(Order order) {if (orderMapper.selectOrderById(order.getOrderId()) == null) {orderMapper.insertOrder(order);} else {orderMapper.updateOrder(order);}// 处理订单的历史记录、支付信息和物流信息等// 这里需要调用额外的Mapper对象来处理其他表的CRUD// orderHistoryMapper.insertOrUpdate(order.getHistory());// paymentInfoMapper.insertOrUpdate(order.getPaymentInfo());// shipmentInfoMapper.insertOrUpdate(order.getShipmentInfo());}public void deleteOrder(String orderId) {orderMapper.deleteOrderById(orderId);// 同时删除相关的订单历史记录、支付信息和物流信息等// orderHistoryMapper.deleteByOrderId(orderId);// paymentInfoMapper.deleteByOrderId(orderId);// shipmentInfoMapper.deleteByOrderId(orderId);}public Order getOrder(String orderId) {return orderMapper.selectOrderById(orderId);}
}

服务层B 只做订单的保存。

public class OrderServiceWithMapperB {private final OrderMapper orderMapper;public OrderServiceWithMapper(OrderMapper orderMapper) {this.orderMapper = orderMapper;}public void createOrder(Order order) {if (orderMapper.selectOrderById(order.getOrderId()) == null) {orderMapper.insertOrder(order);} else {orderMapper.updateOrder(order);}// 处理订单的历史记录、支付信息和物流信息等// 这里需要调用额外的Mapper对象来处理其他表的CRUD// orderHistoryMapper.insertOrUpdate(order.getHistory());// paymentInfoMapper.insertOrUpdate(order.getPaymentInfo());// shipmentInfoMapper.insertOrUpdate(order.getShipmentInfo());}public Order getOrder(String orderId) {return orderMapper.selectOrderById(orderId);}
}

Repository

定义仓储接口

import java.util.Optional;public interface OrderRepository {void saveOrder(Order order);void deleteOrder(String orderId);Optional<Order> findOrderById(String orderId);
}

实现仓储接口

public class OrderRepositoryImpl implements OrderRepository {private final OrderMapper orderMapper;public OrderRepositoryImpl(OrderMapper orderMapper) {this.orderMapper = orderMapper;}@Overridepublic void saveOrder(Order order) {if (orderMapper.selectOrderById(order.getOrderId()) == null) {orderMapper.insertOrder(order);} else {orderMapper.updateOrder(order);}// 处理订单的历史记录、支付信息和物流信息等// orderHistoryMapper.save(order.getHistory());// paymentInfoMapper.save(order.getPaymentInfo());// shipmentInfoMapper.save(order.getShipmentInfo());}@Overridepublic void deleteOrder(String orderId) {orderMapper.deleteOrderById(orderId);// 同时删除相关的订单历史记录、支付信息和物流信息等// orderHistoryMapper.deleteByOrderId(orderId);// paymentInfoMapper.deleteByOrderId(orderId);// shipmentInfoMapper.deleteByOrderId(orderId);}@Overridepublic Optional<Order> findOrderById(String orderId) {return Optional.ofNullable(orderMapper.selectOrderById(orderId));}
}

使用仓储模式的服务层

两处仓储的服务层代码基本一致 全为调用 仓储接口

public class OrderService {private final OrderRepository orderRepository;public OrderService(OrderRepository orderRepository) {this.orderRepository = orderRepository;}public void createOrder(Order order) {orderRepository.saveOrder(order);}public void deleteOrder(String orderId) {orderRepository.deleteOrder(orderId);}public Order getOrder(String orderId) {return orderRepository.findOrderById(orderId).orElseThrow(() -> new RuntimeException("Order not found"));}
}

这里简单说下两者写法的区别和使用仓储模式的好处

职责分离:

Mapper:直接与数据库表交互,完成基本的CRUD操作。服务层需要调用多个Mapper以处理复杂的业务逻辑。
仓储模式:仓储模式在Mapper之上添加了一层抽象,将复杂的业务逻辑封装在仓储实现中,服务层只需调用仓储接口即可。

代码简洁性:

Mapper:由于直接操作数据库,服务层可能会变得复杂,需要处理多个Mapper的调用逻辑。
仓储模式:将复杂的业务逻辑封装在仓储层,服务层代码更加简洁和聚焦。

可维护性:

Mapper:当业务逻辑变更时,服务层可能需要修改大量代码。
仓储模式:业务逻辑集中在仓储层,更容易管理和维护。

扩展性:

Mapper:更换持久化技术时,需要修改所有涉及数据访问的地方。
仓储模式:只需修改仓储的实现部分,服务层无需变动。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1522837.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

绿联充电宝怎么样?深度测评西圣、绿联、倍思磁吸充电宝!

在如今这个电子设备不离手的时代&#xff0c;充电宝成为了我们生活中不可或缺的伙伴。而磁吸充电宝以其便捷的使用方式和时尚的外观&#xff0c;更是受到了众多消费者的青睐&#xff0c;今天&#xff0c;我们将对西圣、绿联、倍思这三个品牌的磁吸充电宝进行深度测评&#xff0…

Three之材质Material

本文目录 前言一、基础材质1.1 特点及属性1.2 代码1.3 效果 二、标准材质2.1 特点及属性2.2 代码及效果 三、深度材质四、法向材质五、朗伯材质六、Phong式材质七、粒子材质八、 着色器材质九、其他材质 前言 Three.js中的材质&#xff08;Material&#xff09;是独立于物体顶点…

Anthropic Claude Artifacts,克劳德聊天机器人如何简化代码编程

最近有一位8岁的小男孩&#xff0c;没有任何编程经验&#xff0c;却成功创建了一个网页游戏。他利用了Claude AI和Cursor来生成代码&#xff0c;这充分展示了人工智能在简化编程和创作过程中的巨大潜力。前几天还能看见一个8岁的女孩用生成式人工智能Cursor ai工具可以搭建出一…

一款基于Vue的低代码可视化表单设计器工具,6K star的可视化表单设计器工具,轻松搞定表单,支持多端适配(附源码)

前言 随着Web应用的日益复杂化&#xff0c;表单的设计与开发成为了许多项目中不可或缺的一环。然而&#xff0c;在实际cao作过程中&#xff0c;表单设计往往面临着重复工作量大、效率低下等问题。那么&#xff0c;是否有一款工具能够简化这一过程&#xff0c;提高开发者的效率…

【MySQL07】【锁】

文章目录 一、前言二、事务的读写情况1. 写-写情况2. 读-写情况3. 一致性读4. 锁定读2.1 共享锁和独占锁2.2 锁定读的语句 5. 写操作 三、多粒度锁四、表锁和行锁1. 表级锁1.1 表级别的 S锁 和 X锁1.2 表级别的 IS 锁和 IX锁1.3 表级别的 AUTO-INC 锁 2. 行级锁2.1 行级锁的分类…

【流式输出】LangChain流式输出的概念

&#x1f601; 作者简介&#xff1a;一名大四的学生&#xff0c;致力学习前端开发技术 ⭐️个人主页&#xff1a;夜宵饽饽的主页 ❔ 系列专栏&#xff1a;JavaScript小贴士 &#x1f450;学习格言&#xff1a;成功不是终点&#xff0c;失败也并非末日&#xff0c;最重要的是继续…

记一次头疼事故:springSecurity无法重定向到登录页/springSecurity整合layui后,会话丢失,点击选项卡无法定位到登录页。

1、问题概述? 1、springboot工程引入了springSecurity权限框架实现用户登录功能,当刷新浏览器地址栏的时候能够自动的重定向到登录页实现登录。 2、但是项目中使用了layui的选项卡,当会话丢失的时候(或者重启工程后直接访问),选项卡无法回到登录页,而是选项卡中的数据表…

yolo数据集钢材表面缺陷v8下载适用yolov5等全版本已标注txt格式

钢材表面缺陷检测数据集介绍 数据集概述 本数据集专为钢材表面缺陷检测任务而设计&#xff0c;包含了大量的钢材表面图像&#xff0c;每张图像均带有详细的缺陷标注信息。数据集旨在帮助研究人员和开发人员训练高精度的目标检测模型&#xff0c;以应用于钢材制造和质量控制等多…

建网站公司策划书

建网站公司策划书&#xff1a;建设创新型网站服务企业 一、背景介绍 随着信息时代的来临&#xff0c;互联网已经成为人们生活和工作的重要组成部分。在这个数字化的时代&#xff0c;企业需要强大的在线存在来吸引客户、展示产品和提供服务。为满足市场需求&#xff0c;我们公…

图形语言传输格式glTF和三维瓦片数据3Dtiles(b3dm、pnts)学习

文章目录 3DTilesb3dm一、glTF1.glTF 3D模型格式有两种2.glTF 场景描述结构3.glTF的JSON结构 二、 3DTiles 原文 工具资料 格式详解 格式详解&#xff01; 3D Tiles 是一种开源的、优化的文件格式&#xff0c;支持逐级细节&#xff08;LOD&#xff09;和空间索引&#xff0c;使…

JMeter 快速入门体验,小白也能看得懂!

最近在推进信创转 arm, 遇到的问题是有几个服务在 x86 架构下运行良好&#xff0c;但是在 arm 机器上总是出现问题&#xff0c;为了验证问题&#xff0c;准备使用压测工具做一下压力测试&#xff0c;JMeter 免费开源又好用&#xff0c;趁此机会学习实践一下吧。 JMeter 是开源…

高德地图-小米14 Pro 定制版 v12.10.61.3021 简洁版

高德地图小米14 Pro 定制版是一款专门为小米14 Pro 设计的简洁版高德地图。相较于普通版本&#xff0c;该版本体积更小&#xff0c;运行速度更快&#xff0c;并且没有广告。支持驾车、骑行、公交地铁、步行等多种导航模式&#xff0c;使用北斗卫星导航系统&#xff0c;精准度非…

【机器人学】7-4.六自由度机器人自干涉检测-两圆柱体空间关系【附MATLAB代码】

目录 前言 公式推导 MATLAB代码 前言 前面介绍了两个圆柱的旋转变换&#xff0c;已将两个圆柱体旋转到了比较好分析的位置&#xff0c;下面将正式分析两个圆柱体的位置关系。会借用投影的思想。 一 根据机械臂的几何数据以及DH参数&#xff0c;确定机械臂等…

硬件产品经理进阶:产品层次划分的3个方法

目录 1、内容简介 2、产品三层次概念 3、产品四层次概念 4、产品五层次概念 作者简介 1、内容简介 产品本身指的是能够满足需求和欲望的一种媒介物。 可以是实体、也可以是虚拟的服务。 在产品竞争白热化的今天&#xff0c; 如果只是考虑把产品做出来、 仅仅在实际产…

保存json时,保存成自己喜欢的格式的方法(而不是直接保存成格式化的json文档)

保存json时&#xff0c;不是直接保存成格式化的json文档的格式的方法 前言&#xff0c;博主是如何把格式话的json格式保存成自己喜欢的json格式的保存成格式化的json文档的格式&#xff1a;带缩进格式全部保存成一行每条数据保存成一行&#xff1a; 保存成自己喜欢的格式碎碎念…

红黑树的插入 C++

红黑树与二叉搜索树类似 它在每个节点增加了一个存储位记录节点的颜色&#xff0c;可以是RED,也可以是BLACK&#xff1b;通过任意一条从根到叶子简单路径上颜色的约束&#xff0c;红黑树保证最长路径不超过最短路径的二倍&#xff0c;因而近似平衡&#xff08;最短路径就是全黑…

深入浅出Stream流

Java 8的新特性之一就是流stream&#xff0c;配合同版本出现的 Lambda &#xff0c;使得操作集合&#xff08;Collection&#xff09;提供了极大的便利。 案例引入 在JAVA中&#xff0c;涉及到对数组、Collection等集合类中的元素进行操作的时候&#xff0c;通常会通过循环的…

学习bat脚本

内容包含一些简单命令或小游戏&#xff0c;在乐趣中学习知识。 使用方法&#xff1a; 新建文本文档&#xff0c;将任选其一代码保存到文档中并保存为ASCII编码。将文件后缀改为.bat或.cmd双击运行即可。 一. 关机脚本 1. 直接关机 echo off shutdown -s -t 00秒直接关机。 2…

亿图图示下载安装教程EdrawMax Pro 13版超详细图文教程

亿图图示下载安装教程EdrawMax Pro 13版超详细图文教程&#xff1a; 亿图图示是一款功能强大的综合绘图软件&#xff0c;具有以下特点和功能 丰富的绘图类型&#xff1a;涵盖 210 余种办公绘图类型&#xff0c;包括流程图、思维导图、信息图、工业设计、组织架构图、平面设计…

Java学习第五天(续)

方法 方法是一种语法结构&#xff0c;它可以把一段代码封装成一个功能&#xff0c;以方便重复调用。 主要分析返回值和形参&#xff0c;只要确定这两个就可以定义方法。 方法调用内存图 方法调用完之后就从栈内存清除走了&#xff1b; 方法参数传递机制&#xff1a; 值传递&a…