Hibernate JPA onetoMany/ManyTone持久化-违反完整性约束-未找到父密钥

Hibernate JPA onetoMany/ManyTone持久化-违反完整性约束-未找到父密钥,hibernate,jpa,Hibernate,Jpa,我的映射文件(相关数据): 家长: @Entity @Table(name = "ATTRIBUTE_NAME", uniqueConstraints = @UniqueConstraint(columnNames = "NAME_TEXT")) @SequenceGenerator(name="ATTRIBUTE_NAME_SEQ", sequenceName="ATTRIBUTE_NAME_SEQ", initialValue = 1, allocationSize = 1) publ

我的映射文件(相关数据):

家长:

@Entity
@Table(name = "ATTRIBUTE_NAME", uniqueConstraints = @UniqueConstraint(columnNames = "NAME_TEXT"))
@SequenceGenerator(name="ATTRIBUTE_NAME_SEQ",    sequenceName="ATTRIBUTE_NAME_SEQ", initialValue = 1, allocationSize = 1)
public class AttributeNameVo implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE,    generator="ATTRIBUTE_NAME_SEQ")
    @Column(name = "ATTRIBUTE_ID", unique = true, nullable = false, precision = 6, scale = 0)
    private int attributeId;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "attributeNameVo")
    private Set<AttributeFunctionalUsageVo> attributeFunctionalUsageVos = new HashSet<AttributeFunctionalUsageVo>(0);
然后我在代码中执行(伪代码):

在DAO中:

  em().persist(attr);
日志结果显示:

select ATTRIBUTE_NAME_SEQ.nextval from dual

insert into ATTRIBUTE_NAME (ACTIVE_FL, DATE_CREATED, DATE_MODIFIED,  DISPLAY_SEQ_NO, EXTERNAL_REF_ID, HINT_TEXT, LOV_FL, MAX_LENGTH, MAX_RANGE, MIN_RANGE, NAME_TEXT, POS_FL, PUBLIC_FL, RAPID_SEARCH_FL, REQUIRED_FL, TYPE_CD, USER_CREATED, USER_MODIFIED, ATTRIBUTE_ID) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)

insert into ATTRIBUTE_FUNCTIONAL_USAGE (DATE_CHANGED, DATE_CREATED, DATE_MODIFIED, USER_CREATED, USER_MODIFIED, ATTRIBUTE_ID, FUNCTIONAL_AREA_CD) values (?, ?, ?, ?, ?, ?, ?)
然后是错误:

ORA-02291: integrity constraint (ATTR_FUNCTIONAL_USAGE_ATTRB_FK) violated - parent key not found
希望您能帮助解决此问题。我尝试了很多东西,但什么都没有

根据注释中的问题,可嵌入id的实体映射为:

public class AttributeFunctionalUsageIdVo implements Serializable {

@Column(name = "ATTRIBUTE_ID", nullable = false, precision = 6, scale = 0)
private int attributeId;

好的,出于临时目的,我已经解决了这个问题,方法是先进行持久化,然后刷新,以获得具有“id”的父记录。然后我循环遍历“持久化”记录中的子对象,并手动“设置”它对应的FK


同样,这不是一个完美的解决方案,效率也很低,但它似乎已经成功了。。。如果有人能提出更优雅、更好的解决方案,我将不胜感激。如果我看到更好的东西,我会接受这个答案

您的解决方案是必需的,因为您已将AttributeFunctionalUsageVo中的attributeNameVo映射设置为只读(insertable=false,Updateable=false),因此JPA需要检查可嵌入ID中“attributeId”字段的其他映射以设置其值。如果不使用值手动更新该字段,则在插入时该字段为空,这就是失败的原因

根据您使用的JPA版本,有许多选项。如果必须使用JPA 1.0,则可以修改映射,使AttributeName EVO可写,而Embedded has中的映射为只读(在两个映射上切换可插入、可更新的设置)。然后,JPA将从关系中提取'attributeId'字段,忽略对embeddedid字段的任何更改。这将导致它为null,除非您刷新或从数据库中重新加载实体

JPA2.0引入了其他选项,例如允许将关系标记为ID,甚至声明连接字段。然后,您将使用:

@ManyToOne(fetch = FetchType.LAZY)
@MapsId("attributeId")
private AttributeNameVo attributeNameVo;

其中“attributeId”是嵌入ID内映射的名称。JPA随后将使用AttributeName EVO的主键在embeddedID中设置attributeId值,并正确处理插入。

embeddedID类是如何定义的?请提供它,以便更好地理解关系模型。
AttributeFunctionalUsageVo
实体中的AttributeFunctionalUsageIdVo.id.attributeId字段是否对应于
AttributeNameVo
实体的主键?我在上面的编辑中提供了AttributeFunctionalUsageIdVo类。是的,它确实与AttributeFunctionalUsageVo表中的主键相对应,只是为了澄清不一致性:1)实体中没有
AttributeListValueAllIdVo
,是否应该改为
AttributeFunctionalUsageIdVo
?2) 伪代码持续存在
AttributeVo
-是否应该改为
AttributeNameVo
?它确实与AttributeFunctionalUsageVo表中的主键相对应-更具体地说:Embedded correcate中的
attributeId
是否与相同要在父实体中
attributeId
?@wypiperz-我更正了嵌入的id类。此外,是的,可嵌入id和父实体中的attributeId是相同的。然而,hibernate似乎不喜欢这样,而且服务器无法启动。事实上,我使用的是JPA2.0。我将尝试使用“@MapsId”解决方案,并在下周之前报告。您有2个到该字段的映射。您应该将其中一个insertable和updateable设置为true,而将另一个标记为false。MapsId是更好的选项,但是如果您正确设置了映射,您仍然应该找到服务器无法启动的原因。我尝试使用@MapsId。Persist工作正常,将生成的id和propagtes检索到子实体。但是,在提交时,我得到了错误:
ORA-00972:identifier太长
insert语句显示为:
insert-into-ATTRIBUTE\u FUNCTIONAL\u用法(DATE\u更改、DATE\u创建、DATE\u修改、USER\u创建、USER\u修改、**id\u-attributenamevo\u-ATTRIBUTE\u id**、FUNCTIONAL\u-AREA\u-CD)值(?、、、、、?)
有什么帮助吗?最后确定!!!让它工作起来。。我想我仍然需要
@JOIN\u COLUMN
注释以及
@MapsId
。我会认为你的回答已被接受。谢谢“id_attributenamevo_ATTRIBUTE_id”是JPA规范定义的默认联接列,当联接列不存在时。很高兴它起作用了
public class AttributeFunctionalUsageIdVo implements Serializable {

@Column(name = "ATTRIBUTE_ID", nullable = false, precision = 6, scale = 0)
private int attributeId;
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("attributeId")
private AttributeNameVo attributeNameVo;