【问题标题】:JPA onetoMany/ManytoOne persist - integrity constraint violated - parent key not foundJPA onetoMany/ManytoOne 坚持 - 违反完整性约束 - 未找到父键
【发布时间】:2019-05-09 03:39:43
【问题描述】:

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

家长:

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

孩子:

@Entity
@Table(name = "ATTRIBUTE_FUNCTIONAL_USAGE")
public class AttributeFunctionalUsageVo implements Serializable {

        @EmbeddedId
        @AttributeOverrides({@AttributeOverride(name = "attributeId", column = @Column(name = "ATTRIBUTE_ID", nullable = false, precision = 6, scale = 0) ),
                             @AttributeOverride(name = "functionalAreaCd", column = @Column(name = "FUNCTIONAL_AREA_CD", nullable = false, length = 5) ) })
        private AttributeFunctionalUsageIdVo id;

        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "attributeId", referencedColumnName="ATTRIBUTE_ID", nullable = true, insertable = false, updatable = false)
        private AttributeNameVo attributeNameVo;

然后我做代码(伪代码):

  AttributeNameVo attr = new AttributeNameVo();
  AttributeFunctionalUsageVo attrFunc = new AttributeFunctionalUsageVo();
  attr.getAttributeFunctionalUsageVos().add(attrFunc);
  attrFunc.setAttributeNameVo(attr);

在 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;

【问题讨论】:

  • EmbeddedId 类是如何定义的?请提供它以更好地理解关系模型。 AttributeFunctionalUsageVo实体中的AttributeFunctionalUsageIdVo.id.attributeId字段是否对应AttributeNameVo实体的主键?
  • 我在上面的编辑中提供了 AttributeFunctionalUsageIdVo 类。是的,它确实对应于 AttributeFunctionalUsageVo 表中的主键
  • 只是为了澄清不一致之处:1)实体中没有AttributeListValueAllIdVo - 应该是AttributeFunctionalUsageIdVo 吗? 2) 伪代码持续存在AttributeVo - 应该改为AttributeNameVo 吗?
  • 它确实对应于 AttributeFunctionalUsageVo 表中的主键 - 更具体地说:嵌入中的 attributeId 是否对应(相同)到 attributeId在您的父实体中?
  • @wypieprz - 我更正了嵌入的 id 类。另外,是的,可嵌入的 id 和父实体中的 attributeId 是相同的。

标签: hibernate jpa


【解决方案1】:

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

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

JPA 2.0 引入了其他选项,例如允许将关系标记为 ID,甚至声明连接字段 maps to the Id 字段。然后你会使用:

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

其中“attributeId”是嵌入 ID 中的映射名称。然后,JPA 将使用 AttributeNameVo 的主键为您设置 EmbeddedID 中的 attributeId 值,并正确处理插入。

【讨论】:

  • 我已经尝试过的第一件事是设置 (insertable=true, updatable=false) 。但是,休眠似乎不喜欢这样,服务器无法启动我实际上使用的是 JPA 2.0。我将尝试 '@MapsId' 解决方案并在下周报告。
  • 您有 2 个到该字段的映射。您应该将其中一个将可插入和可更新设置为 true,而将另一个标记为 false。 MapsId 是更好的选择,但如果您正确设置了映射,您仍然应该找出服务器无法启动的原因。
  • 我尝试使用@MapsId。 Persist 可以正常工作并检索生成的 id 并传播到子实体。但是,在提交时我收到错误:ORA-00972: identifier is too long 插入语句显示为:insert into ATTRIBUTE_FUNCTIONAL_USAGE (DATE_CHANGED, DATE_CREATED, DATE_MODIFIED, USER_CREATED, USER_MODIFIED, **id_attributenamevo_ATTRIBUTE_ID**, FUNCTIONAL_AREA_CD) values (?, ?, ?, ?, ?, ?, ?) 任何帮助??
  • 终于好了!!!让它工作..我想我仍然需要@JOIN_COLUMN注释以及@MapsId。我会将您的答案标记为已接受。谢谢!!
  • "id_attributenamevo_ATTRIBUTE_ID" 是当连接列不存在时 JPA 规范定义的默认连接列。很高兴它正在工作
【解决方案2】:

好的,因此出于 TEMP 的目的,我通过持久化然后刷新以获取具有“id”的父记录来解决此问题。然后我遍历“持久”记录中的子对象并手动“设置”它对应的 FK。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-19
    • 2018-04-18
    相关资源
    最近更新 更多