具有未知PK / FK属性的级联持久性JPA实体违反NotNullConstraint [英] Cascade persist JPA entities with unknown PK/FK attributes violates NotNullConstraint

查看:122
本文介绍了具有未知PK / FK属性的级联持久性JPA实体违反NotNullConstraint的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想坚持一个有很多1:1或1:多关系的JPA实体,只有一次调用 persist

I would like to persist a JPA entity with many 1:1 or 1:many relationships with only one call to persist.

问题:实体的主键是自动生成的,并用作子实体中的外键。提交事务时,会在子实体的外键列上指出违反NotNullConstraint的异常。

Problem: the entity's primary key is auto generated and used as a foreign key in a child entity. When the transaction is committed, there is an exception pointing out a violated NotNullConstraint on the child entity's foreign key column.


内部异常:java。 sql.SQLException:ORA-01400:插入
NULL(SCHEMA。PROTOCOL_FILE。PROTOCOL_ID)不可能

Internal Exception: java.sql.SQLException: ORA-01400: Insertion of NULL in ("SCHEMA"."PROTOCOL_FILE"."PROTOCOL_ID") not possible

父实体:

@Entity
@Table(name = "...")
public class Protocol {

    @Id
    @GeneratedValue(generator="SQ_PROTOCOL", strategy=GenerationType.SEQUENCE)
    @SequenceGenerator(name="SQ_PROTOCOL", sequenceName="SQ_PROTOCOL", allocationSize=50)
    @Column(name = "PROTOCOL_ID")
    private Long protocolId;

    @OneToOne(mappedBy="protocol", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private ProtocolFile file;

    //Other attributes and getter/setter omitted
}

子实体:

@Entity
@Table(name = "PROTOCOL_FILE")
public class ProtocolFile {

    @Id
    @Column(name = "PROTOCOL_ID")
    private Long protocolId;

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
    @JoinColumns(@JoinColumn(name="PROTOCOL_ID", referencedColumnName="PROTOCOL_ID", updatable=false, insertable=false))
    private Protocol protocol;

    //Other attributes and getter/setter omitted
}

您是否知道一个方便的解决方案,所以我可以在一次通话中保留属于协议的所有实体?

Do you know a convenient solution, so I can persist all entities, that belong to Protocol, in one call?

推荐答案

这里的情况是 ProtocolFile 的派生身份 - 的I​​D ProtocolFile 协议的I​​D,它们之间存在一对一的关系。

The situation you have here is a "derived identity" of the ProtocolFile - the ID of the ProtocolFile is the ID of the Protocol and there is a one-to-one relationship between them.

我看到你正在使用 updatable = false,insertable = false 但是最好遵循建议使用 @MapsId的规范注释:

I see you are using updatable=false, insertable=false but it's better to follow the specs which suggest to use the @MapsId annotation:

@Entity
@Table(name = "PROTOCOL_FILE")
public class ProtocolFile {

    @Id // No @Column here
    private Long protocolId;

    @MapsId // --- HERE
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
    @JoinColumn(name="PROTOCOL_ID") // Just that
    private Protocol protocol;
}

或者你可能想跳过 protocolId 字段,并在关系上放置 @Id 注释。

Or you may want to skip the protocolId field altogether and put the @Id annotation on the relationship.

@Entity
@Table(name = "PROTOCOL_FILE")
public class ProtocolFile {

    @Id // --- HERE
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
    @JoinColumn(name="PROTOCOL_ID") // Just that
    private Protocol protocol;
}

当然,您需要设置协议创建期间文件的实例,不再在以后更改(例如,仅允许使用 ProtocolFile <设置它/ code> constructor)。

Of course, you need to set the protocol instance to the file during creation and not change it later any more (eg. allow to set it only using the ProtocolFile constructor).

请参阅 JPA 2.0规范了解更多详细信息和示例(示例4 似乎是你的情况)。

See section "2.4.1 Primary Keys Corresponding to Derived Identities" of the JPA 2.0 spec for more details and examples (Example 4 seems to be your case).

这篇关于具有未知PK / FK属性的级联持久性JPA实体违反NotNullConstraint的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆