具有多个相同类型的值对象的聚合根问题
Posted
技术标签:
【中文标题】具有多个相同类型的值对象的聚合根问题【英文标题】:Problem with aggregate root with more than one value object of the same type 【发布时间】:2021-08-25 07:34:22 【问题描述】:我是 Spring Data JDBC 的新手,我使用 Spring-Boot 2.5.0、Java 11 和 Lombok(简化的代码示例)创建了一个包含两个 Address 值的 Customer 聚合。
我有一个客户实体(聚合根)和一个地址值对象
@Data
@Builder
@AllArgsConstructor
class Customer
@Id Long id;
String name;
Address address1;
Address address2;
@Data
@Builder
@AllArgsConstructor
class Address
String city;
和一个客户实体的存储库
@Repository
public interface CustomeRepository extends CrudRepository<Customer, Long>
使用 Postgres 的 db 架构如下所示
CREATE TABLE "customer" (
"id" BIGSERIAL NOT NULL,
"name" VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE "address" (
"id" BIGSERIAL NOT NULL,
"customer" BIGINT,
"city" VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
);
创建和存储客户
var address1 = Address.builder().city("New York").build();
var address2 = Address.builder().city("Chicago").build();
var customer = Customer.builder().name("Joe").address1(address1).address2(address2).build();
var result = customerRegistry.save(customer);
到目前为止一切都很好,数据库中的条目看起来也很好
id | name
----+------
1 | Joe
id | customer | city
----+----------+----------
1 | 1 | Chicago
2 | 1 | New York
所以期待一位客户,但这样做时
var customers = customerService.findAll();
customers.forEach(c -> log.debug("Customer: ", c));
输出将是
Customer(id=1, name=Joe, address1=Address(city=New York), address2=Address(city=Chicago))
Customer(id=1, name=Joe, address1=Address(city=Chicago), address2=Address(city=Chicago))
Customer(id=1, name=Joe, address1=Address(city=New York), address2=Address(city=New York))
Customer(id=1, name=Joe, address1=Address(city=Chicago), address2=Address(city=New York))
然后这样做
var customer = customerRepository.getById(result.getId());
会导致
org.springframework.dao.IncorrectResultSizeDataAccessException: Incorrect result size: expected 1, actual 4
顺便说一句。如果客户只有一个地址字段,一切都会按预期进行。
所以我错过了什么还是这是一个错误?
【问题讨论】:
【参考方案1】:您可以将@Column
注释放在一个或两个属性上,指定用于反向引用Customer
的不同列。
例如:
class Customer
@Id Long id;
String name;
@Column("first")
Address address1;
@Column("second")
Address address2;
期望以下address
表
CREATE TABLE "address" (
"id" BIGSERIAL NOT NULL,
"first" BIGINT,
"second" BIGINT,
"city" VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
);
如需了解更多背景信息和超出当前特定问题的其他替代方案,请参阅Why is a entity - value relationship implemented as a back reference in Spring Data JDBC
【讨论】:
您好 Jens,非常感谢您的快速回复!实际上,我使用 Map 之类的地图来表示三种不同的地址类型。它工作正常,但我认为你的建议是更好的解决方案。来自弗伦斯堡的感谢和问候,Stefan 第一和第二列应该在客户表还是地址表中? @Gaurav 在地址表中 确切的地址将存储在哪里,我正在考虑将第一个和第二个作为地址 ID @Gaurav 对不起,我不明白你的问题。address
中的 id
不是必需的,我建议不要这样做。 first
和 second
的组合是独一无二的。以上是关于具有多个相同类型的值对象的聚合根问题的主要内容,如果未能解决你的问题,请参考以下文章
如何在plsql中将对象类型属性的值分配给具有相同属性属性的不同对象类型?
DDD领域驱动设计实战-聚合(Aggregate)和聚合根(AggregateRoot)