在Spring Data R2DBC中设计一对一和一对多关系



在使用Spring Data R2DBC设计一对一和一对多关系时,我正在探索可能的想法。

由于Spring Data R2DBC仍然不支持本机关系,因此仍然需要自己处理这些关系(与Spring Data JDBC不同(。

我想,当涉及到一对一映射时,实现可能看起来像这样:

@Table("account")
public class Account {

@Id
private Long id;

@Transient // one-to-one
private Address address;
}
@Table("address")
public class Address {

@Id
private Integer id;
}

而数据库模式将定义如下:

--address
CREATE TABLE address
(
id                  SERIAL PRIMARY KEY
)

--account
CREATE TABLE account
(
id                     SERIAL PRIMARY KEY,
address_id             INTEGER REFERENCES address(id)
)

由于Account对象是我的聚合根,我想我应该按照Jens Schaduer的建议加载Address对象:

聚合是组成一个单元的对象集群始终保持一致。此外,它应该始终保持(并且加载(在一起。来源:Spring Data JDBC、References和Aggregate

这让我想到,在像这样的一对一关系的情况下,我实际上应该像这样定义我的Account实体:

@Table("account")
public class Account {

@Id
private Long id;

@Transient // one-to-one
private Address address;
@Column("address_id")
private Integer addressId;
}

稍后,为了用Address重新创建完整的Account聚合实体,我会写一些类似的东西:

@Service
public class AccountServiceImpl implements AccountService {

private final AccountRepository accountRepository;
private final AddressRepository addressRepository;

public AccountServiceImpl(AccountRepository accountRepository,
AddressRepository addressRepository) {
this.accountRepository = accountRepository;
this.addressRepository = addressRepository;
}

@Override
public Mono<Account> loadAccount(Integer id) {
return accountRepository.getAccountById(id)
.flatMap(account ->
Mono.just(account)
.zipWith(addressRepository.getAddressByAccountId(account.getAddressId()))
.map(result -> {
result.getT1().setAddress(result.getT2());
return result.getT1();
})
);
}
}

如果不是这样,那么在使用Spring Data R2DBC时,我还应该如何处理一对一关系?

我认为你的方法是合理的。这里只有几个挑剔的地方:

  • 你需要flatMap吗?->Mono.just?你不能直接用map
  • 我不认为这是一个服务,而是一个存储库(它不是由SpringData直接实现的
  • 您可能可以在加载后的回调中调用该代码

最新更新