title: How do I properly cascade save a one-to-one, bidirectional relationship on primary key in Hibernate 3.6
body: <p>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.</p>
  
  <p><strong>Owning Entity</strong></p>
  
  <pre><code>@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;
      }
  }
  </code></pre>
  
  <p><strong>Owned Entity</strong></p>
  
  <pre><code>@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;
      }
  }
  </code></pre>
  
  <p>and the code below is being used to save the entity:</p>
  
  <pre><code>LeadAffiliate aff = new LeadAffiliate();
  
  aff.setLead(lead);
  lead.setLeadAffiliate(aff);
  
  em.persist(lead);
  </code></pre>
  
  <p>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:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>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:</p>
  
  <pre><code>@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;
      }
  }
  </code></pre>
  
  <p>However, with these changes I get the same result. (Works in 3.5.0 but not 3.5.6 or 3.6.0)</p>
  
  <p>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 :/.</p>