How do I properly cascade save a one-to-one, bidirectional relationship on primary key in Hibernate 3.6

醉酒当歌 提交于 2019-11-27 06:44:25

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; 

    ...
}
Pascal Thivent

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).

References

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!