JPA onetoMany / ManytoOne持久化 - 违反完整性约束 - 未找到父键

时间:2015-11-19 21:36:45

标签: 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)
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

非常感谢帮助解决此问题。我尝试了很多东西,但没有尝试......

根据评论中的问题,embeddable id的实体映射是:

public class AttributeFunctionalUsageIdVo implements Serializable {

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

2 个答案:

答案 0 :(得分:3)

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

根据您使用的JPA版本,有许多选项。如果必须使用JPA 1.0,则可以修改映射,以便attributeNameVo是可写的,并且embeddable中的映射是只读的(在两个映射上切换可插入的可更新设置)。然后JPA将拉出&#39; attributeId&#39;关系中的字段,忽略对embeddedid id字段的任何更改。除非您从数据库刷新或以其他方式重新加载实体,否则这将导致它为空。

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

  <label for="EditPVComment">PV Comments</label>
<textarea class="maxinputmessage" id="EditPVComment" name="EditPVComment" cols="80" rows="10" maxlength="3000" style="width:400px;">Some text here maybe.</textarea>
<br>
<label for="EditManPVComment">Man PV Comments</label>
<textarea class="maxinputmessage" id="EditManPVComment" name="EditManPVComment" cols="80" rows="10" maxlength="3000" style="width:400px;">Some Man text here maybe.</textarea>

<script>
$().ready(function(){
              var $this = $(".maxinputmessage");

$this.each(function()
{
 var charMaxLen = $(this).attr("maxLength");
var charLen = $(this).val().length;

$(this).after("<em>(Maximim characters: " + charMaxLen + ") You have <span>" + (charMaxLen -     charLen)    +    "</span> characters left.</em>");

$(this).on("keyup",function()
{
    var charMaxLen = $(this).attr("maxLength");
    left = charMaxLen - $(this).val().length;
    $(this).next("em").find("span").text(charMaxLen - $(this).val().length);       
});
});

  });
</script>

&#34; attributeId&#34;是嵌入式ID中映射的名称。然后,JPA将为您设置带有AttributeNameVo主键的embeddedID中的attributeId值,并正确处理插入。

答案 1 :(得分:0)

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

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

相关问题