简体   繁体   English

具有未知PK / FK属性的级联持久JPA实体违反NotNullConstraint

[英]Cascade persist JPA entities with unknown PK/FK attributes violates NotNullConstraint

I would like to persist a JPA entity with many 1:1 or 1:many relationships with only one call to persist . 我想通过一个persist调用来persist具有许多1:1或1:许多关系的JPA实体。

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. 提交事务后,会出现一个异常,指出子实体的外键列上的NotNullConstraint违规。

Internal Exception: java.sql.SQLException: ORA-01400: Insertion of NULL in ("SCHEMA"."PROTOCOL_FILE"."PROTOCOL_ID") not possible 内部异常:java.sql.SQLException:ORA-01400:无法在(“ SCHEMA”。“ PROTOCOL_FILE”。“ PROTOCOL_ID”)中插入NULL

Parent entity: 父实体:

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

Child entity: 子实体:

@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? 您是否知道一个方便的解决方案,因此我可以在一次调用中保留属于Protocol所有实体?

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. 你这里的情况是一种“派生身份” ProtocolFile -中的ID ProtocolFile是的ID Protocol ,并在它们之间存在一个一对一的关系。

I see you are using updatable=false, insertable=false but it's better to follow the specs which suggest to use the @MapsId annotation: 我看到您使用的是@MapsId updatable=false, insertable=false但最好遵循建议使用@MapsId批注的规范:

@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;
}

Or you may want to skip the protocolId field altogether and put the @Id annotation on the relationship. 或者,您可能希望完全跳过protocolId字段,并将@Id注释放在关系上。

@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;
}

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). 当然,您需要在创建过程中将protocol实例设置为file ,并且以后不再更改(例如,仅允许使用ProtocolFile构造函数进行设置)。

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). 有关更多详细信息和示例,请参见JPA 2.0规范的 “ 2.4.1与派生身份相对应的主键”部分( 示例4似乎是您的情况)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM