title: foreign key no parent error
body: <p>This is really why I quit using Hibernate to manage my relationships for me. Too many new gray hairs.</p>
  
  <p>Hibernate 3.6.10</p>
  
  <p>OK, I have two classes, Schedule and Event. Schedule has many events, but an event has only one schedule.</p>
  
  <p>Schedule:</p>
  
  <pre><code>/**
   * 
   */
  package com.heavyweightsoftware.leal.model.schedule;
  
  import java.util.ArrayList;
  import java.util.Collection;
  
  import javax.persistence.CascadeType;
  import javax.persistence.Column;
  import javax.persistence.Entity;
  import javax.persistence.FetchType;
  import javax.persistence.GeneratedValue;
  import javax.persistence.GenerationType;
  import javax.persistence.Id;
  import javax.persistence.JoinColumn;
  import javax.persistence.NamedQueries;
  import javax.persistence.NamedQuery;
  import javax.persistence.OneToMany;
  import javax.persistence.Table;
  
  import com.heavyweightsoftware.leal.helper.DateHelper;
  import com.heavyweightsoftware.leal.model.Pojo;
  
  /**
   * A particular collection of events that can be shared
   * @author Thom
   */
  @Entity
  @Table(name = "SCHEDULE")
  @NamedQueries( {
      @NamedQuery(name = Schedule.COUNT_SCHED_ID,      query =  "SELECT COUNT(*) " +
                                                                "FROM Schedule s " +
                                                                "WHERE s.scheduleId = :scheduleId"),
      @NamedQuery(name = Schedule.COUNT_SCHED_NAME,    query =  "SELECT COUNT(*) " +
                                                                "FROM   ScheduleRole r, Schedule s, SystemUser u " +
                                                                "WHERE  u.email = :email " +
                                                                 " AND u.id = r.systemUserId " +
                                                                 " AND r.scheduleId = s.id " +
                                                                 " AND s.name = :scheduleName "),
      @NamedQuery(name = Schedule.QUERY_EVENTS_BY_USER, query =  "SELECT  r.roleType, s " +
                                                                 "FROM    Schedule s, ScheduleRole r, SystemUser u " +
                                                                 "WHERE   u.email = :email " +
                                                                 "  AND   u.id = r.systemUserId " +
                                                                 "  AND   r.scheduleId = s.id " +
                                                                 " ")
      }
  )
  public class Schedule extends Pojo {
  
      public static final int        LENGTH_SCHEDULE_ID        = 32;
      public static final String     COUNT_SCHED_ID            = "countScheduleId";
      public static final String     COUNT_SCHED_NAME          = "countScheduleName";
      public static final String     QUERY_EVENTS_BY_USER      = "findEventsByUser";
  
      @Column(name = "ID", nullable=false)
      @Id @GeneratedValue(strategy=GenerationType.AUTO)
      private Integer     id;
  
      @Column(name = "NAME", nullable=false)
      private String      name;
  
      @Column(name = "SCHEDULE_ID", nullable=false, unique=true, length=LENGTH_SCHEDULE_ID)
      private String      scheduleId;
  
      @OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER, orphanRemoval=true)
      @JoinColumn(name="ID")
      private Collection&lt;Event&gt;   events;
  
      /**
       * Copy all members from one to the other
       * @param from the from
       * @param to the to
       * @param copySubMembers if true, copy sub members like entity
       */
      public static void copy(Schedule from, Schedule to, boolean copySubMembers){
          to.setId(from.getId());
          to.setName(from.getName());
          to.setScheduleId(from.getScheduleId());
          if(copySubMembers){
              to.setEvents(from.getEvents());
          }
      }
  
      /**
       * no-arg constructor
       */
      public Schedule() {
      }
  
      /**
       * copy constructor
       */
      public Schedule(Schedule schedule) {
          copy(schedule, this, true);
      }
  
      /* (non-Javadoc)
       * @see com.heavyweightsoftware.leal.model.Pojo#toString()
       */
      @Override
      public String toString() {
          StringBuilder sb = new StringBuilder(super.toString());
          sb.append('|');
          sb.append(getName());
          sb.append('|');
          sb.append(getScheduleId());
          sb.append('|');
          sb.append(getEvents());
          return sb.toString();
      }
  
      /* (non-Javadoc)
       * @see java.lang.Object#hashCode()
       */
      @Override
      public int hashCode() {
          final int prime = 31;
          int result = super.hashCode();
          result = prime * result + ((id == null) ? 0 : id.hashCode());
          result = prime * result + ((name == null) ? 0 : name.hashCode());
          result = prime * result
                  + ((scheduleId == null) ? 0 : scheduleId.hashCode());
          return result;
      }
  
      /* (non-Javadoc)
       * @see java.lang.Object#equals(java.lang.Object)
       */
      @Override
      public boolean equals(Object obj) {
          if (this == obj)
              return true;
          if (!super.equals(obj))
              return false;
          if (getClass() != obj.getClass())
              return false;
          Schedule other = (Schedule) obj;
          if (id == null) {
              if (other.id != null)
                  return false;
          } else if (!id.equals(other.id))
              return false;
          if (name == null) {
              if (other.name != null)
                  return false;
          } else if (!name.equals(other.name))
              return false;
          if (scheduleId == null) {
              if (other.scheduleId != null)
                  return false;
          } else if (!scheduleId.equals(other.scheduleId))
              return false;
          return true;
      }
  
      /**
       * @return the id
       */
      public final Integer getId() {
          return id;
      }
  
      /**
       * @param id the id to set
       */
      public final void setId(Integer id) {
          this.id = id;
      }
  
      /**
       * @return the name
       */
      public final String getName() {
          return name;
      }
  
      /**
       * @param name the name to set
       */
      public final void setName(String name) {
          this.name = name;
      }
  
      /**
       * @return
       */
      public String getScheduleId() {
          return scheduleId == null?scheduleId = DateHelper.getUniqueID():scheduleId;
      }
  
      /**
       * @param scheduleId
       */
      public void setScheduleId(String scheduleId) {
          this.scheduleId = scheduleId;
      }
  
      /**
       * @return the events
       */
      public Collection&lt;Event&gt; getEvents() {
          return events==null?events = new ArrayList&lt;&gt;():events;
      }
  
      /**
       * @param events the events to set
       */
      public void setEvents(Collection&lt;Event&gt; events) {
          this.events = events;
      }
  }
  </code></pre>
  
  <p>Event:</p>
  
  <pre><code>/**
   * 
   */
  package com.heavyweightsoftware.leal.model.schedule;
  
  import java.util.Calendar;
  
  import javax.persistence.Column;
  import javax.persistence.Entity;
  import javax.persistence.FetchType;
  import javax.persistence.GeneratedValue;
  import javax.persistence.GenerationType;
  import javax.persistence.Id;
  import javax.persistence.JoinColumn;
  import javax.persistence.ManyToOne;
  import javax.persistence.NamedQueries;
  import javax.persistence.Table;
  import javax.persistence.Temporal;
  import javax.persistence.TemporalType;
  
  import com.heavyweightsoftware.leal.model.Pojo;
  
  /**
   * A particular event entry in a calendar
   * @author Thom
   */
  @Entity
  @Table(name = "EVENT")
  @NamedQueries( {
      }
  )
  public class Event extends Pojo {
  
      /**
       * Length of the randomly generated event ID
       */
      private static final int            LENGTH_EVENT_ID             = 32;
  
      @Column(name = "ID", nullable=false)
      @Id @GeneratedValue(strategy=GenerationType.AUTO)
      private Integer     id;
  
      @Column(name = "START_TIME")
      @Temporal(TemporalType.TIMESTAMP)
      private Calendar    start;
  
      @Column(name = "END_TIME")
      @Temporal(TemporalType.TIMESTAMP)
      private Calendar    end;
  
      @Column(name = "EVENT_NAME", nullable=false)
      private String      eventName;
  
      @Column(name = "EVENT_ID", nullable=false, unique=true, length=LENGTH_EVENT_ID)
      private String      eventId;
  
      @ManyToOne(fetch=FetchType.EAGER)
      @JoinColumn(name="SCHEDULE_ID")
      private Schedule    schedule;
  
      @Column(name = "LOCATION")
      private String      location;
  
      /* (non-Javadoc)
       * @see java.lang.Object#hashCode()
       */
      @Override
      public int hashCode() {
          final int prime = 31;
          int result = super.hashCode();
          result = prime * result + ((end == null) ? 0 : end.hashCode());
          result = prime * result
                  + ((eventName == null) ? 0 : eventName.hashCode());
          result = prime * result + ((id == null) ? 0 : id.hashCode());
          result = prime * result
                  + ((location == null) ? 0 : location.hashCode());
          result = prime * result
                  + ((schedule == null) ? 0 : schedule.hashCode());
          result = prime * result + ((start == null) ? 0 : start.hashCode());
          return result;
      }
  
      /* (non-Javadoc)
       * @see java.lang.Object#equals(java.lang.Object)
       */
      @Override
      public boolean equals(Object obj) {
          if (this == obj)
              return true;
          if (!super.equals(obj))
              return false;
          if (getClass() != obj.getClass())
              return false;
          Event other = (Event) obj;
          if (end == null) {
              if (other.end != null)
                  return false;
          } else if (!end.equals(other.end))
              return false;
          if (eventName == null) {
              if (other.eventName != null)
                  return false;
          } else if (!eventName.equals(other.eventName))
              return false;
          if (id == null) {
              if (other.id != null)
                  return false;
          } else if (!id.equals(other.id))
              return false;
          if (location == null) {
              if (other.location != null)
                  return false;
          } else if (!location.equals(other.location))
              return false;
          if (schedule == null) {
              if (other.schedule != null)
                  return false;
          } else if (!schedule.equals(other.schedule))
              return false;
          if (start == null) {
              if (other.start != null)
                  return false;
          } else if (!start.equals(other.start))
              return false;
          return true;
      }
  
      /* (non-Javadoc)
       * @see com.heavyweightsoftware.leal.model.Pojo#toString()
       */
      @Override
      public String toString() {
          StringBuilder sb = new StringBuilder();
          sb.append(super.toString());
          sb.append('|');
          sb.append(getEventName());
          sb.append('|');
          sb.append(getTimestamp(getStart()));
          sb.append('-');
          sb.append(getTimestamp(getEnd()));
          sb.append("|scheduleId=");
          Schedule schedule = getSchedule();
          sb.append(schedule==null?"null":schedule.getId());
          sb.append('|');
          sb.append(getLocation());
          sb.append('|');
          sb.append(getEventId());
          return sb.toString();
      }
  
      /**
       * @return the id
       */
      public final Integer getId() {
          return id;
      }
  
      /**
       * @param id the id to set
       */
      public final void setId(Integer id) {
          this.id = id;
      }
  
      /**
       * The start date of the event in UTC
       * @return the start
       */
      public final Calendar getStart() {
          return start;
      }
  
      /**
       * The start date of the event in UTC
       * @param start the start to set
       */
      public final void setStart(Calendar start) {
          this.start = start;
      }
  
      /**
       * The end date of the event in UTC
       * @return the end
       */
      public final Calendar getEnd() {
          return end;
      }
  
      /**
       * The end date of the event in UTC
       * @param end the end to set
       */
      public final void setEnd(Calendar end) {
          this.end = end;
      }
  
      /**
       * @return the eventId
       */
      public String getEventId() {
          return eventId;
      }
  
      /**
       * @param eventId the eventId to set
       */
      public void setEventId(String eventId) {
          this.eventId = eventId;
      }
  
      /**
       * @return the eventName
       */
      public final String getEventName() {
          return eventName;
      }
  
      /**
       * @param eventName the eventName to set
       */
      public final void setEventName(String eventName) {
          this.eventName = eventName;
      }
  
      /**
       * @return the location
       */
      public final String getLocation() {
          return location;
      }
  
      /**
       * @param location the location to set
       */
      public final void setLocation(String location) {
          this.location = location;
      }
  
      /**
       * @return the schedule
       */
      public Schedule getSchedule() {
          return schedule;
      }
  
      /**
       * @param schedule the schedule to set
       */
      public void setSchedule(Schedule schedule) {
          this.schedule = schedule;
      }
  }
  </code></pre>
  
  <p>Now at the point I'm getting the exception, I have created a schedule and then added 4 events to the schedule and am calling update on my schedule DAO to save the events. Here is my current code:</p>
  
  <pre><code>public Schedule update(Schedule schedule) {
      //first save the events
      for(Event event:schedule.getEvents()){
          getHibernateTemplate().saveOrUpdate(event); //&lt;-Fails here
      }
      Schedule schedule2 = getHibernateTemplate().get(Schedule.class, schedule.getId());
      Schedule.copy(schedule, schedule2, false);
      System.err.println(schedule2.toString());
      getHibernateTemplate().saveOrUpdate(schedule2);
      return retrieveById(schedule2.getId());
  }
  </code></pre>
  
  <p>All fields on my event are populated except the ID, which is auto generated. Here's the exception:</p>
  
  <pre><code>org.springframework.dao.DataIntegrityViolationException: could not insert: [com.heavyweightsoftware.leal.model.schedule.Event]; SQL [insert into EVENT (ID, END_TIME, EVENT_ID, EVENT_NAME, LOCATION, SCHEDULE_ID, START_TIME) values (default, ?, ?, ?, ?, ?, ?)]; constraint [FK3F47A7AA91E64F]; nested exception is org.hibernate.exception.ConstraintViolationException: could not insert: [com.heavyweightsoftware.leal.model.schedule.Event]
      at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:637)
      at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
      at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
      at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
      at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:737)
      at com.heavyweightsoftware.leal.dao.hibernate.schedule.ScheduleHibernateDAO.update(ScheduleHibernateDAO.java:71)
      at com.heavyweightsoftware.leal.dao.hibernate.schedule.ScheduleHibernateDAO.update(ScheduleHibernateDAO.java:1)
      at com.heavyweightsoftware.leal.service.calendar.impl.CalendarServiceImpl.update(CalendarServiceImpl.java:168)
      at com.heavyweightsoftware.leal.service.calendar.impl.CalendarServiceImplTest.testGetCalendars(CalendarServiceImplTest.java:230)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:601)
      at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
      at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
      at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
      at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
      at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
      at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
      at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
      at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
      at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
      at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
      at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
      at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
      at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
      at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
  Caused by: org.hibernate.exception.ConstraintViolationException: could not insert: [com.heavyweightsoftware.leal.model.schedule.Event]
      at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
      at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
      at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:63)
      at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2346)
      at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2853)
      at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:71)
      at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
      at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:320)
      at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:203)
      at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:129)
      at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
      at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
      at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
      at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
      at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:685)
      at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:677)
      at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:673)
      at org.springframework.orm.hibernate3.HibernateTemplate$16.doInHibernate(HibernateTemplate.java:740)
      at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
      ... 30 more
  Caused by: java.sql.SQLException: integrity constraint violation: foreign key no parent; FK3F47A7AA91E64F table: EVENT
      at org.hsqldb.jdbc.Util.sqlException(Util.java:215)
      at org.hsqldb.jdbc.JDBCPreparedStatement.fetchResult(JDBCPreparedStatement.java:4617)
      at org.hsqldb.jdbc.JDBCPreparedStatement.executeUpdate(JDBCPreparedStatement.java:308)
      at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:93)
      at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:56)
      ... 46 more
  Caused by: org.hsqldb.HsqlException: integrity constraint violation: foreign key no parent; FK3F47A7AA91E64F table: EVENT
      at org.hsqldb.error.Error.error(Error.java:131)
      at org.hsqldb.Constraint.getException(Constraint.java:898)
      at org.hsqldb.Constraint.checkInsert(Constraint.java:816)
      at org.hsqldb.StatementDML.performIntegrityChecks(StatementDML.java:1318)
      at org.hsqldb.StatementDML.insertRowSet(StatementDML.java:795)
      at org.hsqldb.StatementInsert.getResult(StatementInsert.java:139)
      at org.hsqldb.StatementDMQL.execute(StatementDMQL.java:190)
      at org.hsqldb.Session.executeCompiledStatement(Session.java:1294)
      at org.hsqldb.Session.execute(Session.java:956)
      at org.hsqldb.jdbc.JDBCPreparedStatement.fetchResult(JDBCPreparedStatement.java:4609)
      ... 49 more
  </code></pre>
  
  <p>Thanks!
  Heartbroken in Lexington:)</p>