如何正确级联保存Hibernate 3.6中主键上的一对一,双向关系 [英] How do I properly cascade save a one-to-one, bidirectional relationship on primary key in Hibernate 3.6

查看:82
本文介绍了如何正确级联保存Hibernate 3.6中主键上的一对一,双向关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我与共享密钥具有一对一的双向实体关系。当我尝试保存关联的所有者时,我得到关于所拥有方的空id生成异常。我使用hibernate-entitymanager并使用spring进行事务管理。
$ b

拥有实体



< pre $ @Entity
@Table(name =lead)
public class Lead
{
private Long leadId;

私人LeadAffiliate leadAffiliate;

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getLeadId()
{
return leadId;


@OneToOne(cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
LeadAffiliate getLeadAffiliate()
{
return leadAffiliate;


已拥有实体 p>

  @Entity 
@Table(name =lead_affiliate)
公开课LeadAffiliate
{
私有长引导ID;

私人牵头人;

@Id
public Long getLeadId()
{
return leadId;
}

@MapsIdmappedBy =leadAffiliate)
@OneToOne(cascade = CascadeType.All)
@PrimaryKeyJoinColumn
@JoinColumn(name =lead_id )
public Lead getLead()
{
return lead;
}
}

以下代码正用于保存实体:

  LeadAffiliate aff = new LeadAffiliate(); 

aff.setLead(lead);
lead.setLeadAffiliate(aff);

em.persist(lead);

这在hibernate 3.5.0-Final中完全正常。尝试升级到3.5.6-Final或3.6.0.Final时,当我开始获得为LeadAffiliate生成的空ID错误时:

  javax.persistence.PersistenceException:org.hibernate.id.IdentifierGenerationException:生成的id为:class com.sellingsource.bizdev.entities.LeadAffiliate 
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl .java:1214)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1147)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1153)
在org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:678)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java :39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java .lang.reflect.Method.invoke(Method.java:597)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator $ ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
at $ Proxy152.persist(未知源)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.orm.jpa.SharedEntityManagerCreator $ SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java :240)
at $ Proxy120.persist(Unknown Source)
at com.sellingsource.common.dao.JpaGenericDao.create(JpaGenericDao.java:38)
... 64 more
导致:org.hibernate.id.IdentifierGenerationException:生成的空id为:class com.sellingsource.bizdev.entities.LeadAffi liate
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:123)
at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:69)
在org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:179)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135)
at org。 hibernate.impl.SessionImpl.firePersist(SessionImpl.java:799)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:791)
at org.hibernate.engine.EJB3CascadingAction $ 1.cascade (EJB3CascadingAction.java:48)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
at org.hibernate.engine.Cascade.cascade(Cascade.java:
at org.hibernate.event.def.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:450)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:282)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:203)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:129)
at org .hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:69)
at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:179)
at org.hibernate.event .def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61)
at org.hibernate.impl.SessionImpl.firePersist (SessionImpl.java:在org.hibernate.impl.SessionImpl.persist(SessionImpl.java:782 808)

在org.hibernate.impl.SessionImpl.persist(SessionImpl.java:786)
。在组织.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:672)
... 77更

另外,我不确定Lead Affiliate上的注释是否完全正确。他们工作,但似乎有点kludgey。所以我将它们改为:

  @Entity 
@Table(name =lead_affiliate)
公共类LeadAffiliate
{
private Long leadId;

私人牵头人;

@Id
@GenericGenerator(name =foreign,strategy =foreign,parameters = {
@ org.hibernate.annotations.Parameter(name =property ,value =lead)
})
@GeneratedValue(generator =foreign)
public Long getLeadId()
{
return leadId;


@OneToOne(mappedBy =leadAffiliate)
@PrimaryKeyJoinColumn
public Lead getLead()
{
return lead;






$ b

但是,通过这些更改,我得到了相同的结果。 (适用于3.5.0,但不适用于3.5.6或3.6.0)

是否有一种新的方式可以做到这一点,或者这是一个错误?我担心的是,我的代码目前正在工作,因为一个bug:/。

关系的一面:


2.4.1与派生身份对应的主键




实体的标识可能来自另一个实体(
父实体)的
标识,当前
实体( 从属实体)是与父实体多对一或一对一
关系的
所有者,
a外键映射关系

您的情况 LeadAffiliate 是派生的,所以它应该当 Lead 应该被 mappedBy 标记为非拥有方时,作为所有者。以下是3.5.0和3.5.6的工作:

  public class Lead {
@Id @GeneratedValue
私有长引导ID;

@OneToOne(cascade = CascadeType.ALL,mappedBy =lead)
私人LeadAffiliate leadAffiliate;

...
}

  public class LeadAffiliate {
@Id
private long leadId;

@OneToOne @MapsId
私人牵头人;

...
}


I have an one-to-one, bidirectional entity relationship with shared keys. When I attempt to save the owner of the association I get a "null id generated" exception against the owned side of the relationship. I am utilizing hibernate-entitymanager and using spring for transaction management.

Owning Entity

@Entity
@Table(name = "lead")
public class Lead
{
    private Long leadId;

    private LeadAffiliate leadAffiliate;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getLeadId()
    {
        return leadId;
    }

    @OneToOne(cascade = CascadeType.ALL)
    @PrimaryKeyJoinColumn
    public LeadAffiliate getLeadAffiliate()
    {
        return leadAffiliate;
    }
}

Owned Entity

@Entity
@Table(name = "lead_affiliate")
public class LeadAffiliate
{
    private Long leadId;

    private Lead lead;

    @Id
    public Long getLeadId()
    {
        return leadId;
    }

    @MapsIdmappedBy = "leadAffiliate")
    @OneToOne(cascade = CascadeType.All)
    @PrimaryKeyJoinColumn
    @JoinColumn(name = "lead_id")
    public Lead getLead()
    {
        return lead;
    }
}

and the code below is being used to save the entity:

LeadAffiliate aff = new LeadAffiliate();

aff.setLead(lead);
lead.setLeadAffiliate(aff);

em.persist(lead);

This all works perfectly fine in hibernate 3.5.0-Final. When attempting to upgrade to 3.5.6-Final or 3.6.0.Final is when I start getting the "null id generated for LeadAffiliate" error:

javax.persistence.PersistenceException: org.hibernate.id.IdentifierGenerationException: null id generated for:class com.sellingsource.bizdev.entities.LeadAffiliate
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1214)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1147)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1153)
    at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:678)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
    at $Proxy152.persist(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
    at $Proxy120.persist(Unknown Source)
    at com.sellingsource.common.dao.JpaGenericDao.create(JpaGenericDao.java:38)
    ... 64 more
Caused by: org.hibernate.id.IdentifierGenerationException: null id generated for:class com.sellingsource.bizdev.entities.LeadAffiliate
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:123)
    at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:69)
    at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:179)
    at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135)
    at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:799)
    at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:791)
    at org.hibernate.engine.EJB3CascadingAction$1.cascade(EJB3CascadingAction.java:48)
    at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:392)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:335)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:204)
    at org.hibernate.engine.Cascade.cascade(Cascade.java:161)
    at org.hibernate.event.def.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:450)
    at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:282)
    at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:203)
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:129)
    at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:69)
    at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:179)
    at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135)
    at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61)
    at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:808)
    at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:782)
    at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:786)
    at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:672)
    ... 77 more

As an aside, I am not sure that the annotations on Lead Affiliate were quite right to begin with. They worked, but seemed kind of kludgey. So I have since changed them to:

@Entity
@Table(name = "lead_affiliate")
public class LeadAffiliate
{
    private Long leadId;

    private Lead lead;

    @Id
    @GenericGenerator(name = "foreign", strategy = "foreign", parameters = {
                    @org.hibernate.annotations.Parameter(name = "property", value="lead")
    })
    @GeneratedValue(generator = "foreign")
    public Long getLeadId()
    {
        return leadId;
    }

    @OneToOne(mappedBy = "leadAffiliate")
    @PrimaryKeyJoinColumn
    public Lead getLead()
    {
        return lead;
    }
}

However, with these changes I get the same result. (Works in 3.5.0 but not 3.5.6 or 3.6.0)

Is there a new way I need to be doing this or is this a bug? My concern is that my code is currently working because of a bug :/.

解决方案

Specification says that derived entity should be the owning side of the relationship:

2.4.1 Primary Keys Corresponding to Derived Identities

The identity of an entity may be derived from the identity of another entity (the "parent" entity) when the former entity (the "dependent" entity) is the owner of a many-to-one or one-to-one relationship to the parent entity and a foreign key maps the relationship from dependent to parent.

In your case LeadAffiliate is derived, so it should be the owner, when Lead should be marked as non-owning side by mappedBy. The following works in both 3.5.0 and 3.5.6:

public class Lead { 
    @Id @GeneratedValue
    private Long leadId; 

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "lead")
    private LeadAffiliate leadAffiliate; 

    ...
}

.

public class LeadAffiliate {  
    @Id
    private Long leadId;  

    @OneToOne @MapsId
    private Lead lead; 

    ...
}

这篇关于如何正确级联保存Hibernate 3.6中主键上的一对一,双向关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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