Mik*_*ely 40 java orm hibernate jpa jpa-2.0
我与共享密钥有一对一的双向实体关系.当我尝试保存关联的所有者时,我得到了一个"null id generated"异常,对照关系的拥有方.我正在利用hibernate-entitymanager并使用spring进行事务管理.
拥有实体
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
拥有实体
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
并且以下代码用于保存实体:
LeadAffiliate aff = new LeadAffiliate();
aff.setLead(lead);
lead.setLeadAffiliate(aff);
em.persist(lead);
Run Code Online (Sandbox Code Playgroud)
这一切在hibernate 3.5.0-Final中完全正常.当尝试升级到3.5.6-Final或3.6.0.Final时,我开始得到"为LeadAffiliate生成的空id"错误:
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
Run Code Online (Sandbox Code Playgroud)
顺便说一句,我不确定Lead Affiliate的注释是否适合开始.他们工作,但似乎有点kludgey.所以我后来改为:
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,通过这些更改,我得到了相同的结果.(适用于3.5.0但不适用3.5.6或3.6.0)
有没有新方法我需要这样做或这是一个错误?我担心的是我的代码目前正在运行,因为有一个bug:/.
axt*_*avt 43
规范说派生实体应该是关系的拥有方:
2.4.1对应于派生身份的主键
当前实体("从属"实体)是多对一或一对一关系的所有者时,实体的身份可以从另一个实体("父"实体)的身份派生.父实体和外键将关系从依赖映射到父.
在你的情况下LeadAffiliate派生,所以它应该是所有者,何时Lead应该被标记为非拥有方mappedBy.以下适用于3.5.0和3.5.6:
public class Lead {
@Id @GeneratedValue
private Long leadId;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "lead")
private LeadAffiliate leadAffiliate;
...
}
Run Code Online (Sandbox Code Playgroud)
.
public class LeadAffiliate {
@Id
private Long leadId;
@OneToOne @MapsId
private Lead lead;
...
}
Run Code Online (Sandbox Code Playgroud)
我的答案不能解释为什么事情正在使用Hibernate 3.5.0-Final,但不能使用3.5.6-Final或3.6.0.Final(你应该报告这个,我称之为回归).
无论如何,JPA 2.0中以标准方式更好地支持派生标识符,在您的情况下,我认为您可以简单地使用注释来注释您的OneToOne关系Id.
更新:如axtavt所示,当使用派生标识符时,"依赖"实体必须是关系的所有者.因此,依赖实体的完整映射将是:
@Entity
@Table(name = "lead_affiliate")
public class LeadAffiliate {
private Lead lead;
@Id
@OneToOne
@JoinColumn(name="FK")
public Lead getLead() {
return lead;
}
}
Run Code Online (Sandbox Code Playgroud)
而"父母"实体:
@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, mappedBy="lead")
public LeadAffiliate getLeadAffiliate() {
return leadAffiliate;
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个有效的JPA 2.0映射,可与EclipseLink一起使用.但是,Hibernate不喜欢它并且不会实例化EntityManagerFactory(该死!).
作为解决方法,您将必须使用axtavt建议的解决方案,即声明主键属性以及关系属性并在关系属性上使用MapsId.
但上面应该有效,有一个IMO在Hibernate中有一个错误(报告为HHH-5695).
| 归档时间: |
|
| 查看次数: |
68851 次 |
| 最近记录: |