JPA 与存储在不同数据库中的用户实体的多对多关系
JPA Many-to-Many Relationship with Users Entity Stored in a Different Database
TLDR;
我正在尝试创建与存储在不同数据库中的实体(用户)的关系,但不知道如何在 JPA 中执行此操作。
用例
我正在 Spring Boot/JPA 实施汽车服务。我创建了一个名为 Car
的 entity/table。一辆汽车可能有多个车主(用户),一个用户可能拥有多辆汽车。但是,User
table 存储在单独的用户服务中。
由于这是一个多对多的关系,我觉得 JoinTable
比较合适。这里的问题是没有 User
table 可以加入。我只需要将用户的 UUID 存储在连接 table 中,因此 GET
方法可以获取给定用户的所有汽车,或给定汽车的所有车主。
源代码
这是对 Car
实体的尝试。删除 ForeignKey
约束允许在连接 table 中创建条目,而不会由于缺少子 table.
而导致错误
@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 存储库 save()
方法成功创建了连接中的汽车和条目 table:
{
"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);
我收到以下错误:
ERROR: column user1_.id does not exist
Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: could not extract ResultSet; nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not extract ResultSet (through reference chain: java.util.ArrayList[0]->Car["users"])]
如何读回给定用户的汽车列表?我会以错误的方式解决这个问题吗?我对其他实现持开放态度。
如@vincendep 所述,解决方案是删除 User
实体并将 Car
实体中的 users
属性 替换为以下内容:
@ElementCollection
@CollectionTable(name = "car_owner", joinColumns = @JoinColumn(name = "car_id"))
@Column(name = "user_id")
private Set<UUID> owners;
这仍将使用 car_owner
加入 table。可以使用以下模型创建具有多个用户的汽车:
{
"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);
TLDR;
我正在尝试创建与存储在不同数据库中的实体(用户)的关系,但不知道如何在 JPA 中执行此操作。
用例
我正在 Spring Boot/JPA 实施汽车服务。我创建了一个名为 Car
的 entity/table。一辆汽车可能有多个车主(用户),一个用户可能拥有多辆汽车。但是,User
table 存储在单独的用户服务中。
由于这是一个多对多的关系,我觉得 JoinTable
比较合适。这里的问题是没有 User
table 可以加入。我只需要将用户的 UUID 存储在连接 table 中,因此 GET
方法可以获取给定用户的所有汽车,或给定汽车的所有车主。
源代码
这是对 Car
实体的尝试。删除 ForeignKey
约束允许在连接 table 中创建条目,而不会由于缺少子 table.
@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 存储库 save()
方法成功创建了连接中的汽车和条目 table:
{
"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);
我收到以下错误:
ERROR: column user1_.id does not exist Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: could not extract ResultSet; nested exception is com.fasterxml.jackson.databind.JsonMappingException: could not extract ResultSet (through reference chain: java.util.ArrayList[0]->Car["users"])]
如何读回给定用户的汽车列表?我会以错误的方式解决这个问题吗?我对其他实现持开放态度。
如@vincendep 所述,解决方案是删除 User
实体并将 Car
实体中的 users
属性 替换为以下内容:
@ElementCollection
@CollectionTable(name = "car_owner", joinColumns = @JoinColumn(name = "car_id"))
@Column(name = "user_id")
private Set<UUID> owners;
这仍将使用 car_owner
加入 table。可以使用以下模型创建具有多个用户的汽车:
{
"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);