我有父(Property)和子(Credit)之間的關係,我的Hibernate配置對我很好,只要我不嘗試通過家長(財產)通過Cascade保存新的子女(信用)。JPA/Hibernate @OneToMany在JoinTable上帶有可選Child - 保存父節點影響JoinTable上的多個插入
Hibernate的配置:
@Entity
public class Property implements Ownable {
...
@Valid
// ALSO TRIED WITH CascadeType.ALL !!!
@OneToMany(fetch = LAZY, cascade = {PERSIST, MERGE, REMOVE}, orphanRemoval = true)
@JoinTable(
name = "PROPERTY_CREDIT_OPTIONS",
joinColumns = @JoinColumn(name="PROPERTY_ID", nullable = false),
inverseJoinColumns = @JoinColumn(name = "CREDIT_ID", nullable = false, unique = true)
)
List<NotActiveCredit> creditOptions = new ArrayList<>();
...
}
@Entity
public class NotActiveCredit extends Credit {
@ManyToOne
@JoinTable(
name = "PROPERTY_CREDIT_OPTIONS",
inverseJoinColumns = @JoinColumn(name="PROPERTY_ID", nullable = false),
joinColumns = @JoinColumn(name = "CREDIT_ID", nullable = false, unique = true)
)
@NotNull @NonNull
Property property;
}
控制器電話:
@PostMapping("/save")
public String save (
@ModelAttribute("property") @Valid Property formProperty,
BindingResult errors,
ModelMap modelMap
) {
if (!errors.hasErrors()) {
// formProperty has new Credit in the creditOptions List
// SAVE ONLY DELEGATS TO SPRING DATA REPOSITORY ...
final Property savedProperty = propertyService.save(formProperty);
...
} else {
// BLABLA
}
}
的記錄是這樣的:
Enter InvestmentController.save(...)
Enter PropertyServiceImpl.save(...)
insert into not_active_credit (id, interest_rate_nominal_in_percent, name_of_institution, redemption_at_begin_in_percent, special_redemption_each_year_in_percent) values (default, ?, ?, ?, ?)
binding parameter [1] as [NUMERIC] - [null]
binding parameter [2] as [VARCHAR] - [test]
binding parameter [3] as [NUMERIC] - [null]
binding parameter [4] as [NUMERIC] - [null]
insert into property_credit_options (property_id, credit_id) values (?, ?)
binding parameter [1] as [BIGINT] - [1]
binding parameter [2] as [BIGINT] - [1]
Exit PropertyServiceImpl.save Returns Property
// THEN WHEN IT CLOSE THE TRANSACTION IT WANTS TO INSERT JOIN TABLE AGAIN!
insert into property_credit_options (property_id, credit_id) values (?, ?)
binding parameter [1] as [BIGINT] - [1]
binding parameter [2] as [BIGINT] - [1]
SQL Error: -104, SQLState: 23505
integrity constraint violation: unique constraint or index violation; SYS_PK_10222 table: PROPERTY_CREDIT_OPTIONS
編輯: 附加信息。調用存儲庫之後。保存列表仍被視爲髒(髒=真)。它不應該是假的,當它剛剛被保存時,因爲在控制檯中,我可以看到它只是發送SQL到數據庫插入。在調試時,如果我給列表的髒= false,那麼第二次插入將不會觸發更多,一切都很好。爲什麼在將插入數據發送到數據庫之後沒有將其設置爲false。它不應該更髒,或者我認爲是錯誤的?
SOLUTION
由於crizzis建議我在Property
類中刪除@JoinTable
從集合屬性creditOptions
並添加mappedBy='property'
。該集合現在可以從父級更新。
@Valid
@OneToMany(mappedBy="property", fetch = LAZY, cascade = ALL, orphanRemoval = true)
Collection<NotActiveCredit> creditOptions = new ArrayList<>();
論NotActiveCredit
類的另一邊是如下:
@ManyToOne
@JoinTable(
name = "PROPERTY_CREDIT_OPTIONS",
inverseJoinColumns = @JoinColumn(name="PROPERTY_ID", nullable = false),
joinColumns = @JoinColumn(name = "CREDIT_ID", nullable = false, unique = true)
)
@NotNull
Property property;
嘿,真棒,我剛從'NotActiveCredit'類中刪除了JoinTable,它已經可以工作了。 'mappedBy'不是必需的。 –
這仍然會被視爲一個單獨的映射。唯一的區別是'@ ManyToOne'默認使用連接列,因此您可能會在'NONACTIVECREDIT'表中看到額外的'PROPERTY_ID'列。更重要的是,'Property.creditOptions'和'NotActiveCredit.property'不會被JPA – crizzis
保持同步表'not_active_credit'只創建一個'property_id',但我會仔細看看同步。順便說一句。 @ManyToOne註釋沒有'mappedBy',你會在哪裏建議添加它?謝謝。 –