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
My answer won't explain why things are working with Hibernate 3.5.0-Final but don't with 3.5.6-Final or 3.6.0.Final (and you should report this, I call this a regression).
Anyway, derived identifiers are much better supported in JPA 2.0, in a standard way, and in your case, I think you could simply annotate your OneToOne
relation with an Id
annotation.
Update: As underlined by axtavt, when using a derived identifier, the "dependent" entity must be the owner of the relationship. So the full mapping for the dependent entity would be:
@Entity
@Table(name = "lead_affiliate")
public class LeadAffiliate {
private Lead lead;
@Id
@OneToOne
@JoinColumn(name="FK")
public Lead getLead() {
return lead;
}
}
And the "parent" 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, mappedBy="lead")
public LeadAffiliate getLeadAffiliate() {
return leadAffiliate;
}
}
This is a valid JPA 2.0 mapping, and works with EclipseLink. However, Hibernate doesn't like it and won't instantiate the EntityManagerFactory
(dammit!).
As workaround, you'll have to use the solution suggested by axtavt i.e. to declare a primary key attribute as well as the relationship attribute and to use MapsId
on the relationship attribute.
But the above should work, there is IMO a bug in Hibernate (reported as HHH-5695).
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;
...
}