在Java中如何设计领域对象模型_Java业务建模解析

小婷同学_3193

小婷同学_3193

2026-01-10

474人浏览

原创

DDD在Java中落地的核心是让领域对象承载业务语义:封装行为而非仅数据,值对象不可变且重写equals/hashCode,聚合根明确边界并隔离持久化细节。

在java中如何设计领域对象模型_java业务建模解析

Domain-Driven Design

(DDD)在 Java 中落地,核心不是堆砌注解或套用框架,而是让对象真正承载业务语义。领域对象模型不是数据库表的镜像,也不是 DTO 的变体,它得能回答“这个对象能做什么”“它什么时候是合法的”“它的状态如何被改变”。

领域对象必须封装行为,不能只有 getter/setter

很多团队把 Order 类写成纯数据容器:一堆 private 字段 + public getter/setter。这导致业务逻辑散落在 OrderService 里,Order 自身无法表达“订单可以取消”“已发货的订单不能改地址”这类规则。

正确做法是把校验和状态变更逻辑收进领域对象内部:

public class Order {
    private OrderStatus status;
    private Address shippingAddress;

    public void changeShippingAddress(Address newAddress) {
        if (status == OrderStatus.SHIPPED) {
            throw new IllegalStateException("Cannot modify address after shipment");
        }
        this.shippingAddress = newAddress;
    }

    public void cancel() {
        if (status == OrderStatus.CANCELLED) return;
        if (status == OrderStatus.SHIPPED) {
            throw new IllegalStateException("Shipped order cannot be cancelled");
        }
        this.status = OrderStatus.CANCELLED;
    }
}

关键点:

  • changeShippingAddress() 和 cancel() 是命令方法,不是 setter;它们隐含前置条件与副作用
  • 字段保持 private,不暴露 setStatus() 这类危险接口
  • 构造函数应强制满足基本不变量(如 orderId 非空、创建时间必设)

值对象(Value Object)要不可变且重写 equals/hashCode

像 Money、Address、PhoneNumber 这类对象,本质是“值”,不是“身份”。Java 中常见错误是把它做成可变类,或直接用 String 代替。

例如:Address 若可变,两个订单共用同一 Address 实例,一处改了街道,另一处也跟着变——这不是业务事实,是 bug。

正确实现要点:

  • 所有字段 final,构造后不可变
  • 不提供 setter,也不暴露可变集合(如返回 Collections.unmodifiableList())
  • 必须重写 equals() 和 hashCode(),基于字段内容比较(IDE 可自动生成)
  • 推荐使用记录类(record)简化: public record Address(String street, String city, String zipCode) {}

聚合根(Aggregate Root)要控制边界和一致性

一个常见误区是把整个订单系统建模为单个大聚合:把 Order、OrderItem、Payment、LogEntry 全塞进一个 @Aggregate 注解里。结果是并发更新冲突频繁、持久化性能差、事务太长。

聚合根的核心职责是:维护其内部实体/值对象之间的一致性约束,并对外提供唯一访问入口。

java-api-doc-generator
java-api-doc-generator

分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。

下载

例如:

  • Order 是聚合根,OrderItem 是其内部实体,生命周期依附于订单
  • Payment 应是独立聚合,有自己 ID 和生命周期;订单只持有一个 paymentId 引用,而非嵌入整个 Payment 对象
  • 跨聚合的操作(如“支付成功后更新订单状态”)必须通过领域事件或应用层协调,不能在 Order 内部直接调用 payment.confirm()

否则会模糊边界,导致测试困难、数据库耦合、分布式事务陷阱。

JPA/Hibernate 不是领域模型的默认载体

直接用 @Entity 标记领域对象,很快会遇到矛盾:

  • JPA 要求无参构造函数,但领域对象应通过有参构造保证合法性
  • @OneToMany 加载策略常导致 N+1 查询,而领域层不该暴露这种技术细节
  • 为了映射方便加 @Transient 或 @JsonIgnore,污染了领域语义

更稳健的做法是分层隔离:

  • 领域层定义纯净的 Order、OrderItem,不含任何 JPA 注解
  • 持久化层用单独的 OrderJpaEntity 映射表结构,由仓储(OrderRepository)负责在两者间转换
  • 转换逻辑放在仓储实现内,而非领域对象中(避免引入 javax.persistence 包)

这样,当你需要换数据库、加缓存、切分微服务时,领域模型本身不受影响。

最难的不是写出符合 DDD 术语的类,而是每次加一个字段、改一个方法时,都问一句:这个改动是否改变了业务含义?它是否破坏了某个不变量?有没有人会在别处绕过这个逻辑?

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

java js json gate

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

2113

5

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.07

3434

5

hibernate和mybatis有哪些区别
hibernate和mybatis有哪些区别

hibernate和mybatis的区别:1、实现方式;2、性能;3、对象管理的对比;4、缓存机制。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

302

5

Hibernate框架介绍
Hibernate框架介绍

本专题整合了hibernate框架相关内容,阅读专题下面的文章了解更多详细内容。

2025.08.06

2993

15

Java Hibernate框架
Java Hibernate框架

本专题聚焦 Java 主流 ORM 框架 Hibernate 的学习与应用,系统讲解对象关系映射、实体类与表映射、HQL 查询、事务管理、缓存机制与性能优化。通过电商平台、企业管理系统和博客项目等实战案例,帮助学员掌握 Hibernate 在持久层开发中的核心技能。

2025.09.02

8100

14

Hibernate框架搭建
Hibernate框架搭建

本专题整合了Hibernate框架用法,阅读专题下面的文章了解更多详细内容。

2025.10.14

858

8

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.02

6979

3

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

2023.10.19

3208

3

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

2025.10.17

5189

12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习