【发布时间】:2017-07-08 13:32:46
【问题描述】:
我在父(属性)和子(信用)之间有关系,只要我不尝试通过父(属性)级联保存新的子(信用),我的休眠配置就可以正常工作。
休眠配置:
@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
编辑: 附加信息。在调用 Repository.Save 之后,列表仍然被认为是脏的 (dirty=true)。当它刚刚保存时,它不应该是错误的,因为在控制台中我可以看到它只是将 SQL 发送到 db 进行插入。在调试时,如果我给 List 设置了dirty=false,那么第二次 Insert 将不会被触发,一切都很好。为什么在将插入发送到数据库后不将其设置为 false。不应该再脏一点,还是我想错了?
解决方案
正如 crizzis 所建议的,我从 Property 类中的集合属性 creditOptions 中删除了 @JoinTable,并添加了 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;
【问题讨论】:
标签: hibernate jpa spring-data-jpa one-to-many jointable