java - 选择具有知情自然 ID 的实体,而不是尝试插入(JPA 和 SpringBoot)
问题描述
所以基本上我有以下需求。一个人将通过 Rest Controller 发布一个名为“Expense Report”的实体。
该实体有一个 Country 字段,它实际上是与另一个实体的关联。
@EqualsAndHashCode(callSuper = true)
@Entity
@Table(name = "EXPENSE_REPORTS")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ExpenseReport extends BaseEntity {
@Column(name = "TRIP_DESCRIPTION", nullable = false)
private String tripDescription;
@Column(name = "JUSTIFICATION")
private String justification;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "COUNTRY_ID")
private Country country;
@Column(name = "TRIP_START_DATE")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate tripStartDate;
@Column(name = "TRIP_END_DATE")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate tripEndDate;
@Column(name = "TOTAL_AMOUNT")
private BigDecimal totalAmount;
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name="USER_ID")
private User user;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name="EXPENSE_ITEM_ID")
private Set<ExpenseItem> expenses;
}
@EqualsAndHashCode(callSuper = true)
@Entity
@Table(name = "COUNTRIES")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Country extends BaseEntity {
@Column(name = "NAME")
@NaturalId
private String name;
}
我想要检查的是,调用者是否有可能只是发送国家的自然 ID(在这种情况下是名称)和 JPA 而不是尝试插入这个国家,他会找到具有相同名称的国家并关联它。
所以,而不是发送这个帖子:
{
"tripDescription": "Some trip description...",
"justification": "Some justification...",
"country": {
"id": 12345
}
}
他发送这个:
{
"tripDescription": "Some trip description...",
"justification": "Some justification...",
"country": {
"name": "BR"
}
}
我可以想象如何在存储库实现中执行此操作,但我想知道在 JPA 中是否有自动执行此操作的功能。
提前致谢。
解决方案
使用如下关联,而不是 COUNTRIES.COUNTRY_ID 使用 COUNTRIES.NAME
public class ExpenseReport extends BaseEntity {
@Column(name = "TRIP_DESCRIPTION", nullable = false)
private String tripDescription;
@Column(name = "JUSTIFICATION")
private String justification;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = “NAME”,referencedColumnName = "name" ) //Do not use COUNTRY_ID
private Country country;
….
}
public class Country extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "NAME”,nullable = false, updatable = false, unique = true)
@NaturalId(mutable = false)
private String name;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Country)) {
return false;
}
Product naturalIdCountry = (Country) o;
return Objects.equals(getName(), naturalIdCountry.getName());
}
@Override
public int hashCode() {
return Objects.hash(getName());
}
}
推荐阅读
- javascript - how to find exact number from url parameters inside td element
- android - android动画没有延迟
- javascript - 如何修复“TypeError:无法在'CanvasRenderingContext2D'上执行'drawImage'”?
- julia - Julia 作为非 CS 领域专家的工作语言?
- variables - Jenkinsfile中变量内的变量
- javascript - 链接样式表后 CSS/JS 动画不起作用
- database - 对象名称作为 Logtalk 中的变量
- sql - 不同 ID 的最旧记录 - SparkSQL
- html - Angular throws ExpressionChangedAfterItHasBeenCheckedError
- javascript - 使用 jQuery 隐藏除给定 data-* 属性之外的所有元素