简体   繁体   English

JPA 与存储在不同数据库中的用户实体的多对多关系

[英]JPA Many-to-Many Relationship with Users Entity Stored in a Different Database

TLDR; TLDR;

I'm trying to create a relationship to an entity (users) stored in a different database and can't figure out how to do this in JPA.我正在尝试创建与存储在不同数据库中的实体(用户)的关系,但无法弄清楚如何在 JPA 中执行此操作。

Use Case用例

I am implementing a car service in Spring Boot/JPA.我正在 Spring Boot/JPA 中实施汽车服务。 I have created an entity/table called Car .我创建了一个名为Car的实体/表。 A car may have multiple owners (users) and a user may own multiple cars.一辆车可能有多个所有者(用户),一个用户可能拥有多辆汽车。 However, the User table is stored in a separate user service.但是, User表存储在单独的用户服务中。

Since this is a many-many relationship, I felt a JoinTable would be appropriate.由于这是一个多对多的关系,我觉得JoinTable是合适的。 The problem here is that there is no User table to join to.这里的问题是没有要加入的User表。 I just need to store the users' UUIDs in the join table, so GET methods can fetch all cars for a given user, or all owners of a given car.我只需要将用户的 UUID 存储在连接表中,因此GET方法可以获取给定用户或给定汽车的所有车主的所有汽车。

在此处输入图像描述

Source Code源代码

Here's an attempt at the Car entity.这是对Car实体的尝试。 Removing the ForeignKey constraint allows entries to be created in the join table without causing an error due to the missing child table.删除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;
}

Here's the User entity - required for the JPA JoinTable , but only used for its ID:这是User实体 - JPA JoinTable所需的实体,但仅用于其 ID:

@Data
@Entity
@EqualsAndHashCode()
public class User {

  @Id private UUID id;

  @ManyToMany(mappedBy = "users")
  @JsonIgnore
  private Set<Car> cars;
}

Sending the model below to a JPA Repository save() method creates the car and entries in the join table successfully:将下面的 model 发送到 JPA 存储库save()方法成功地在连接表中创建汽车和条目:

{
  "model": "Ford Model T",
  "price": 850.00,
  "users": [
    {"id": "e048b593-aad9-4285-b3e6-49475ad9bd1d"},
    {"id": "1d0f7b1e-bc36-4b99-80a1-8835779598ca"}
  ]
}

Problem Statement问题陈述

However, when I try to retrieve all cars belonging to a specific user ID:但是,当我尝试检索属于特定用户 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);

I get the following error:我收到以下错误:

ERROR: column user1_.id does not exist Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: could not extract ResultSet;错误:列 user1_.id 不存在已解决 [org.springframework.http.converter.HttpMessageNotWritableException:无法写入 JSON:无法提取 ResultSet; nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not extract ResultSet (through reference chain: java.util.ArrayList[0]->Car["users"])]嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException: 无法提取 ResultSet (通过参考链: java".

How can I read back the list of cars for a given user?如何读回给定用户的汽车列表? Am I going about this the wrong way?我会以错误的方式解决这个问题吗? I'm open to other implementations.我对其他实现持开放态度。

As @vincendep mentioned, the solution is to drop the User entity and replace the users property in the Car entity with the following:正如@vincendep 提到的,解决方案是删除User实体并将Car实体中的users属性替换为以下内容:

@ElementCollection
@CollectionTable(name = "car_owner", joinColumns = @JoinColumn(name = "car_id"))
@Column(name = "user_id")
private Set<UUID> owners;

This will still use the car_owner join table.这仍将使用car_owner连接表。 A car can be created with multiple users with the following model:可以使用以下 model 创建具有多个用户的汽车:

{
  "model": "Ford Model T",
  "price": 850.00,
  "owners": [
    "32a7967d-8580-418d-b53a-221ed0c52222",
    "a708455c-c37c-4712-a7ce-59c9be5a5eb5"
  ]
}

You can query cars by user ID as follows (credit to @vincendep):您可以按用户 ID 查询汽车,如下所示(感谢 @vincendep):

@Query(value = "from Car c where :ownerId member of c.owners")
List<Car> findByUserId(UUID ownerId);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM