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

问题描述

我实现了@ModelToOne关系,并希望通过Thymeleaf使用下拉列表。我使用一个单独的公式来保存PlaceEntities,并使用WorkEntities的公式来从上面提到的下拉列表中选择一个合适的Place。当前的实现迫使我添加一个Place,否则WorkEntity将不会保留。当我尝试保存表单而未从下拉列表中选择位置时,出现以下错误:

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

我已经尝试在@ManyToOne端添加“可选= true”条件(无论如何默认情况下为true)或@JoinColumn(nullable = true),但这些都不起作用。

使用选定的位置保存表单就像一个超级按钮一样,但是如果我要保留一个没有PlaceEntity的WorkEntity(这意味着外键列必须为null),该怎么办?

编辑: 我可以自己解决这个问题。错误来自模板的第一个选项标签中的th:value =“”。它创建一个零参数而不是null,而不是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,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>

解决方法

我想问题是Work实体指向尚不存在的Place。您可以将外键标记为deferrable initially deferred或确保调用persistmerge的顺序正确。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...