JPA 与存储在不同数据库中的用户实体的多对多关系
Posted
技术标签:
【中文标题】JPA 与存储在不同数据库中的用户实体的多对多关系【英文标题】:JPA Many-to-Many Relationship with Users Entity Stored in a Different Database 【发布时间】:2021-08-11 12:43:49 【问题描述】:TLDR;
我正在尝试创建与存储在不同数据库中的实体(用户)的关系,但不知道如何在 JPA 中执行此操作。
用例
我正在 Spring Boot/JPA 中实现汽车服务。我创建了一个名为Car
的实体/表。一辆车可能有多个所有者(用户),一个用户可能拥有多辆汽车。但是,User
表存储在单独的用户服务中。
由于这是一个多对多的关系,我觉得JoinTable
是合适的。这里的问题是没有要加入的User
表。我只需要将用户的 UUID 存储在连接表中,因此GET
方法可以获取给定用户或给定汽车的所有车主的所有汽车。
源代码
这是Car
实体的尝试。删除ForeignKey
约束允许在连接表中创建条目,而不会由于缺少子表而导致错误。
@Data
@Entity
@Table(name = "car")
@EqualsAndHashCode(callSuper = true)
public class Car
@Id @GeneratedValue private UUID id;
@ManyToMany
@JoinTable(
name = "car_owner",
joinColumns = @JoinColumn(name = "car_id"),
inverseJoinColumns = @JoinColumn(name = "user_id", insertable = false, updatable = false),
foreignKey = @ForeignKey(name="user_id", value = ConstraintMode.NO_CONSTRAINT))
private Set<User> users;
private String model;
private double price;
这是 User
实体 - JPA JoinTable
所必需的,但仅用于其 ID:
@Data
@Entity
@EqualsAndHashCode()
public class User
@Id private UUID id;
@ManyToMany(mappedBy = "users")
@JsonIgnore
private Set<Car> cars;
将下面的模型发送到 JPA Repository save()
方法会成功创建连接表中的汽车和条目:
"model": "Ford Model T",
"price": 850.00,
"users": [
"id": "e048b593-aad9-4285-b3e6-49475ad9bd1d",
"id": "1d0f7b1e-bc36-4b99-80a1-8835779598ca"
]
问题陈述
但是,当我尝试检索属于特定用户 ID 的所有汽车时:
@Query(
value = "select * from car c inner join car_owner co on c.id = co.car_id where co.user_id = :userId",
nativeQuery = true)
List<Car> findByUserId(UUID userId);
我收到以下错误:
错误:列 user1_.id 不存在 已解决[org.springframework.http.converter.HttpMessageNotWritableException:无法写入JSON:无法提取ResultSet;嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException: could not extract ResultSet (through reference chain: java.util.ArrayList[0]->Car["users"])]
如何回读给定用户的汽车列表?我会以错误的方式解决这个问题吗?我对其他实现持开放态度。
【问题讨论】:
是存储在同一个数据库但不同的架构还是不同的数据库服务器? 如果是同一个数据库,但是schema不同,可以在当前schema中创建一个视图,查询多个schema。但如果它是一个不同的数据库,我也不确定 @SridharPatnaik 用户数据库尚未创建,但我想使用微服务架构,这需要将这两个服务解耦(不同的数据库)。 如果用户由其他服务管理,您的汽车服务中不应包含用户实体。所以只需使用 @ElementCollection 私有 SetUser
实体和JoinTable
。但我仍然不清楚如何将car_owner
表和列与@ElementCollection
映射。将继续朝这个方向寻找。谢谢!
【参考方案1】:
正如@vincendep 所述,解决方案是删除User
实体并将Car
实体中的users
属性替换为以下内容:
@ElementCollection
@CollectionTable(name = "car_owner", joinColumns = @JoinColumn(name = "car_id"))
@Column(name = "user_id")
private Set<UUID> owners;
这仍将使用car_owner
连接表。可以使用以下型号创建具有多个用户的汽车:
"model": "Ford Model T",
"price": 850.00,
"owners": [
"32a7967d-8580-418d-b53a-221ed0c52222",
"a708455c-c37c-4712-a7ce-59c9be5a5eb5"
]
您可以按如下方式通过用户 ID 查询汽车(感谢 @vincendep):
@Query(value = "from Car c where :ownerId member of c.owners")
List<Car> findByUserId(UUID ownerId);
【讨论】:
查询也应该是这样的 @Query(value = "FROM Car c WHERE :owner MEMBER OF c.owners") List以上是关于JPA 与存储在不同数据库中的用户实体的多对多关系的主要内容,如果未能解决你的问题,请参考以下文章