【问题标题】:HIbernate not inserting due to not-nullconstraint with composite FK由于复合 FK 的非空约束,HIbernate 未插入
【发布时间】:2022-01-14 07:28:25
【问题描述】:

我正在尝试使用 Hibernate 保存一个复杂实体,其中我们有多个具有复合键的实体。 当我尝试保存时,Hibernate 似乎没有从具有复合键的子实体上的某些列中正确检索值,因此 postgre 返回非空违规错误。

@Entity
@Table(name = "activities", schema = "ptw")
@Data
@TypeDefs({
        @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class),
        @TypeDef(name = "pg-id-uuid", typeClass = PostgresIdUUIDType.class)
})
public class Activity extends AuditAtBy implements Serializable {

@EmbeddedId
private CommonId commonId;

@MapsId("siteId")
@ManyToOne
@OnDelete(action = OnDeleteAction.CASCADE)
@Type(type = "pg-id-uuid")
@JoinColumn(name="site_id",referencedColumnName = "id", columnDefinition = "uuid", updatable = false)
private Site site;

@ManyToOne()
@JoinColumnsOrFormulas(value = {
        @JoinColumnOrFormula(formula = @JoinFormula(value="location_id", referencedColumnName = "id")),
        @JoinColumnOrFormula(formula = @JoinFormula(value="site_id", referencedColumnName = "site_id"))})
@Type(type = "pg-id-uuid")
@OnDelete(action = OnDeleteAction.CASCADE)
private Location location;

@ManyToOne
@JoinColumns({
        @JoinColumn(name = "job_pack_id", referencedColumnName = "id", columnDefinition = "uuid", insertable = false, updatable = false),
        @JoinColumn( name = "site_id", referencedColumnName="site_id", columnDefinition = "uuid", insertable = false, updatable = false)
})
@Type(type = "pg-id-uuid")
@OnDelete(action = OnDeleteAction.CASCADE)
private JobPack jobPack;

@Column(name = "permit_number", nullable = false, length = 10)
private String permitNumber;

@Column(name = "order_number", nullable = false)
private short orderNumber;


@Column(name = "location_name", length = 200)
private String locationName;

**@ManyToOne
@JoinColumns({
        @JoinColumn(name = "state_id", referencedColumnName="id", columnDefinition = "uuid", insertable = false, updatable = false),
        @JoinColumn(name = "site_id", referencedColumnName="site_id", columnDefinition = "uuid", insertable = false, updatable = false)
})
@Type(type = "pg-id-uuid")
private ActivityState state;**

@ManyToOne
@JoinColumns({
        @JoinColumn(name = "activity_type_id", referencedColumnName="id", columnDefinition = "uuid", insertable = false, updatable = false),
        @JoinColumn(name = "site_id", referencedColumnName="site_id", columnDefinition = "uuid", insertable = false, updatable = false)
})
@Type(type = "pg-id-uuid")
@OnDelete(action = OnDeleteAction.CASCADE)
private ActivityType activityType;




public UUID getId(){
    return this.getCommonId().getId();
}

public void setId(UUID id){
    if (this.getCommonId() == null) {
        this.setCommonId(new CommonId());
    }
    this.getCommonId().setId(id);
}

public void setSite(Site site){
    this.site = site;
    if (this.getCommonId() == null) {
        this.setCommonId(new CommonId());
    }
    this.getCommonId().setSiteId(site.getId());
}
}

在使用映射器从 DTO 转换为实体时,会覆盖 setId/getId/setSite 以更新实体

ActivityState如下:

@Entity
@Table(name = "activity_states", schema = "ptw")
@Data
@TypeDefs({
        @TypeDef(name = "pg-id-uuid", typeClass = PostgresIdUUIDType.class)
})
public class ActivityState extends AuditAtBy implements Serializable {

    @EmbeddedId
    private CommonId commonId;

    @MapsId("siteId")
    @ManyToOne
    @OnDelete(action = OnDeleteAction.CASCADE)
    private Site site;

    @Column(nullable = false, length = 50)
    private String name;

    @Column(name = "icon_id", nullable = false)
    private short iconId;

    @Column(name = "is_initial", nullable = false)
    private boolean isInitial;

    @Column(name = "order_number", nullable = false)
    private short orderNumber;

    public UUID getId(){
        return this.getCommonId().getId();
    }

    public void setId(UUID id){
        if (this.getCommonId() == null) {
            this.setCommonId(new CommonId());
        }
        this.getCommonId().setId(id);
    }

    public void setSite(Site site){
        this.site = site;
        if (this.getCommonId() == null) {
            this.setCommonId(new CommonId());
        }
        this.getCommonId().setSiteId(site.getId());
    }
}

当我尝试保存异常时:

Caused by: org.postgresql.util.PSQLException: ERROR: null value in column "state_id" violates not-null constraint
  Detail: Failing row contains (c821ff72-de93-4c03-abf5-e18347c29955, null, 0, 5081790f-19ed-44e0-be17-94f94aed878b, null, null, test, test, null, 1, 1, f, N/A, 1, null, null, null, null, null, null, null, null, null, null, null, f, {"title": "test", "DateTable": {"timeTo": "", "timeFrom": "", "v..., 2021-12-09 13:46:02.829157+01, 2021-12-09 13:46:02.829157+01, 7b0702c7-9f11-4a92-bfdf-7f98eb8ac94d, 7b0702c7-9f11-4a92-bfdf-7f98eb8ac94d, null, null, f).

尽管我尝试了多种更改映射和关系的方法,但我不知道如何解决。 我知道复合键不是最好的方法,但我们有一个多租户系统,其中保持数据隔离的最佳方法就是这个。

【问题讨论】:

  • 您对insertable = false, updatable = false 有什么期望?您已强制 HBN 不在 DB 中填充 state_id 的值,而 HBD 没有这样做。
  • 没有它,我无法映射实体。当我尝试删除该值时,我设置了这个:实体映射中的重复列:com.basf.swift.ptw.model.entity.Activity 列:site_id(应该用 insert="false" update="false" 映射)因为我需要将多个实体映射到同一列 site_id。
  • 已修复:stackoverflow.com/questions/4231452/… 使用 @JoinColumnsOrFormulas 允许我们删除 insertable= false 并使其正常工作。
  • 为什么不将那个 state_id 连接列标记为 insertable=true?您可以将其他 site_id 连接列保留为 insertable/updatable=false 以避免它被更改并影响实体的身份。
  • 其实你做不到。启动应用程序时 HIbernate 将失败,JoinColumns 注释中的所有列都需要具有相同的标志,因此两者或它们都可插入或不可插入。为了避免这个问题,我们发现这种方法是可行的。 @JoinColumnsOrFormulas(value = { @JoinColumnOrFormula(column = @JoinColumn(name="state_id", referencedColumnName = "id")), @JoinColumnOrFormula(formula = @JoinFormula(value="site_id", referencedColumnName = "site_id")) } )

标签: java spring hibernate jpa spring-data-jpa


【解决方案1】:

答案基本上是这个帖子的第一个答案:Should Hibernate be able to handle overlapping foreign keys?

基本上将映射更改为将实际列作为列,并将在其他实体中重复的映射作为现在正在工作的公式:

@JoinColumnsOrFormulas(value = { 
@JoinColumnOrFormula(column = @JoinColumn(name="state_id", referencedColumnName = "id")), 
@JoinColumnOrFormula(formula = @JoinFormula(value="site_id", referencedColumnName = "site_id")) })

【讨论】:

    猜你喜欢
    • 2019-01-02
    • 1970-01-01
    • 2014-10-08
    • 1970-01-01
    • 1970-01-01
    • 2021-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多