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

前端 未结 2 435
借酒劲吻你
借酒劲吻你 2020-11-29 23:37

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

相关标签:
2条回答
  • 2020-11-30 00:21

    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

    • JPA 2.0 Specification
      • Section 2.4.1 "Primary Keys Corresponding to Derived Identities" (lengthy, covers many cases)
    • JPA Wikibook
      • Primary Keys through OneToOne Relationships
    0 讨论(0)
  • 2020-11-30 00:34

    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; 
    
        ...
    }
    
    0 讨论(0)
提交回复
热议问题