【问题标题】:Kotlin Hibernate @ManyToOne MERGE violates foreign key constraint (Postgres)Kotlin Hibernate @ManyToOne MERGE 违反外键约束(Postgres)
【发布时间】:2021-02-14 15:54:05
【问题描述】:

我实现了@ModelToOne 关系,并希望通过 Thymeleaf 使用下拉列表。我使用单独的公式来持久化 PlaceEntities 和 WorkEntities 的公式,可以从提到的下拉列表中选择适当的 Place。当前的实现强制我添加一个 Place,否则 WorkEntity 将不会被持久化。当我尝试在未从下拉列表中选择地点的情况下保存表单时,会出现以下错误:

错误:在表“work”上插入或更新违反了外键约束“fklyi06ir16ujsbylbtf5k33rmv” 详细信息:键 (place_of_premiere_id)=() 不在表“place”中。

我已经尝试将“optional = true”条件(在任何情况下默认为 true)或 @JoinColumn(nullable = true) 添加到 @ManyToOne Side,但这些都不起作用。

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

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

我的固定控制器:

@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...

我的 ThymeleafTemplate 的下拉菜单:

                <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>

【问题讨论】:

    标签: hibernate kotlin thymeleaf many-to-one constraintviolationexception


    【解决方案1】:

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

    【讨论】:

    • 感谢您的提示。该错误是由第一个选项标记中的 th:value="" 引起的。它不是 null 它生成一个零参数的 Place 对象,它不能被持久化。不需要更改外键约束。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    • 2012-07-15
    • 2017-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多