具有多个相同类型的值对象的聚合根问题 [英] Problem with aggregate root with more than one value object of the same type

查看:46
本文介绍了具有多个相同类型的值对象的聚合根问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 Spring Data JDBC 的新手,并使用 Spring-Boot 2.5.0、Java 11 和 Lombok(代码示例简化)创建了一个具有两个地址值的 Customer 聚合.

I'm new to Spring Data JDBC and create a Customer aggregate with two Address values using Spring-Boot 2.5.0, Java 11 and Lombok (code examples simplified).

我有一个 Customer 实体(聚合根)和一个 Address 值对象

I have one Customer entity (aggregate root) and one Address value object

@Data
@Builder
@AllArgsConstructor
class Customer {
    @Id Long id;
    String name;
    Address address1;
    Address address2;
}

@Data
@Builder
@AllArgsConstructor
class Address {
    String city;
}

和 Customer 实体的一个 Repository

and one Repository for the Customer entity

@Repository
public interface CustomeRepository extends CrudRepository<Customer, Long> {
}

使用 Postgres 的数据库架构看起来像这样

Using Postgres the db schema looks like this

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);

到目前为止一切顺利,数据库中的条目也很好

So far so good, also the entries in the database looking fine

 id | name 
----+------
  1 | Joe


 id | customer |   city   
----+----------+----------
  1 |        1 | Chicago
  2 |        1 | New York

所以期待一位客户,但在这样做时

So expecting one Customer, but when doing this

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

顺便说一句.如果客户只有一个地址字段,则一切都按预期工作.

Btw. If the Customer has only one address field everything works as expected.

所以我错过了什么还是这是一个错误?

So do I miss something or is this a bug?

推荐答案

您可以在一个或两个属性上添加 @Column 批注,指定不同的列以用于对 客户.

You can put a @Column annotation on one or both attributes, specifying different columns to use for the back-reference to 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)
);

有关超出手头特定问题的更多背景和其他替代方案,请参阅为什么实体 - 值关系实现为Spring Data JDBC 中的反向引用

For more background and other alternatives that go beyond the specific problem at hand see Why is a entity - value relationship implemented as a back reference in Spring Data JDBC

这篇关于具有多个相同类型的值对象的聚合根问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆