Kotlin Hibernate@ManyToOne MERGE违反了外键约束(Postgres)



我实现了@ModelToOne关系,并希望通过Thymelaf使用下拉列表。我使用一个单独的公式器来持久化PlaceEntities,并使用一个WorkEntities的公式器,其中可以从提到的下拉列表中选择适当的位置。当前的实现迫使我添加一个Place,否则WorkEntity将不会持久化。当我试图在没有从下拉列表中选择地点的情况下保存表格时,会出现以下错误:

错误:插入或更新表"工作;违反外键约束";fklyi06ir16ujsbylbtf5k33rmv";细节:键(place_of_premee_id(=((不存在于表"中;地方";。

我已经尝试添加";可选=真";condition(在任何情况下默认为true(或@JoinColumn(nullable=true(添加到@ManyToOne Side,但这些都不起作用。

用选定的Place保存表单很有魅力,但如果我想保留一个没有PlaceEntity的WorkEntity(这意味着外键列必须为null(,我该怎么做?

编辑:我可以自己解决这个问题。错误来自于th:value="在我的模板的第一个选项标签中。它创建了一个不能持久化的零args位置对象,而不是null。我在控制器中放了一个if语句,这可能不是最优雅的方法,但我不知道如何在Thymelaf中使th:value=nullable。

我的固定控制器:

@PostMapping(value = ["/addWork"])
fun addWork(@Validated work: Work?, bindingResult: BindingResult): String {
if (bindingResult.hasErrors()) {
print(bindingResult.allErrors)
}

work?.apply {
if (placeOfPremiere?.id == "") {
this.placeOfPremiere = null
}
}
workService.create(work!!)
return "editor/addWork"
}

所有实体的抽象类:

@MappedSuperclass
abstract class Entity(
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
open var id: String?,
open var title: String?,
open var created: OffsetDateTime,
open var modified: OffsetDateTime

儿童:

@Entity
@Table(name = "work")
class WorkEntity(
id: String? = null,
title: String? = null,
created: OffsetDateTime = OffsetDateTime.now(),
modified: OffsetDateTime = OffsetDateTime.now(),
var opus: String? = null,
var dateOfCreation: String? = null,
var dateOfPremiere: String? = null,
@JsonManagedReference
@ManyToOne(
fetch = FetchType.LAZY,
cascade = [CascadeType.MERGE]
) 
var placeOfPremiere: PlaceEntity? = null,
...Other Properties...equals...hashcode...

父级:

@Entity
@Table(name = "place")
class PlaceEntity(
id: String? = null,
title: String? = null,
created: OffsetDateTime = OffsetDateTime.now(),
modified: OffsetDateTime = OffsetDateTime.now(),
var name: String? = null,
var locality: String? = null,
var country: String? = null,
@Embedded
@AttributeOverrides(
AttributeOverride(name = "latitude", column = Column(name = "latitude")),
AttributeOverride(name = "longitude", column = Column(name = "longitude"))
)
var coordinates: CoordinatesEntity? = CoordinatesEntity(),
@JsonBackReference
@OneToMany(mappedBy = "placeOfPremiere")
var relatedWorks: MutableSet<WorkEntity>? = mutableSetOf()              
...Other Properties...equals...hashcode...

ThymelafTemplate的下拉菜单:

<div class="form-group">
<label for="places">Places</label>
<select th:field="*{placeOfPremiere.id}" class="form-control" id="places"
name="Place of Premiere">
<option th:value="">Select Places</option>
<option
th:each="place : ${places}"
th:value="${place.id}"
th:text="${place.title}">
</option>
</select>
<span th:if="${#fields.hasErrors('placeOfPremiere')}" th:errors {placeOfPremiere}"></span>
</div>

我想问题是Work实体引用了一个还不存在的Place。将外键标记为deferrable initially deferred,或者确保调用persistmerge的顺序正确。

最新更新