具有多个相同类型的值对象的聚合根的问题
Problem with aggregate root with more than one value object of the same type
我是 Spring 数据 JDBC 的新手,使用 Spring-Boot 2.5.0、Java 11 和 Lombok 创建一个包含两个地址值的客户聚合(代码示例已简化)。
我有一个客户实体(聚合根)和一个地址值对象
@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 的数据库模式如下所示
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
顺便说一句。如果客户只有一个地址字段,则一切正常。
我是不是遗漏了什么或者这是一个错误?
您可以在一个或两个属性上放置 @Column
注释,指定不同的列用于向后引用 Customer
。
例如:
class Customer {
@Id Long id;
String name;
@Column("first")
Address address1;
@Column("second")
Address address2;
}
期望以下 address
table
CREATE TABLE "address" (
"id" BIGSERIAL NOT NULL,
"first" BIGINT,
"second" BIGINT,
"city" VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
);
有关超出手头特定问题的更多背景和其他替代方案,请参阅
我是 Spring 数据 JDBC 的新手,使用 Spring-Boot 2.5.0、Java 11 和 Lombok 创建一个包含两个地址值的客户聚合(代码示例已简化)。
我有一个客户实体(聚合根)和一个地址值对象
@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 的数据库模式如下所示
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
顺便说一句。如果客户只有一个地址字段,则一切正常。
我是不是遗漏了什么或者这是一个错误?
您可以在一个或两个属性上放置 @Column
注释,指定不同的列用于向后引用 Customer
。
例如:
class Customer {
@Id Long id;
String name;
@Column("first")
Address address1;
@Column("second")
Address address2;
}
期望以下 address
table
CREATE TABLE "address" (
"id" BIGSERIAL NOT NULL,
"first" BIGINT,
"second" BIGINT,
"city" VARCHAR(255) NOT NULL,
PRIMARY KEY (id)
);
有关超出手头特定问题的更多背景和其他替代方案,请参阅