1

My entities are as follows:

@Entity
@Table(name="`surveys`")
@Inheritance
@DiscriminatorColumn(name="`type`")
public abstract class Survey implements Serializable, Comparable<Survey> {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Integer id;

    [...]
}

Above abstract Survey can have two kinds of concrete class:

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorValue(value="SV")
public class SupervisorSurvey extends Survey implements Serializable {

    @OneToOne(mappedBy="supervisorSurvey",cascade=CascadeType.ALL)
    private SurveyPair surveyPair;

    [...]
}

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorValue(value="US")
public class UserSurvey extends Survey implements Serializable {

    @OneToOne(mappedBy="userSurvey",cascade=CascadeType.ALL)
    private SurveyPair surveyPair;

    [...]
}

Then an instance of SurveyPair grabs one of both kinds:

@Entity
@Table(name="`surveypairs`")
public class SurveyPair implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;

    @OneToOne
    @JoinColumn(name="`userSurveyId`",unique=true)
    private UserSurvey userSurvey;

    @OneToOne
    @JoinColumn(name="`supervisorSurveyId`",unique=true)
    private SupervisorSurvey supervisorSurvey;
}

Now the problem: after I create the objects like this:

// survey pair
SurveyPair surveyPair = new SurveyPair(reference);

// user side
UserSurvey usSurvey = new UserSurvey(user);
usSurvey.setSurveyPair(surveyPair);
surveyPair.setUserSurvey(usSurvey);

// supervisor side
SupervisorSurvey svSurvey = new SupervisorSurvey(Application.getLoggedUser(), user);
svSurvey.setSurveyPair(surveyPair);
surveyPair.setSupervisorSurvey(svSurvey);

SurveyInput.getInstance().persist(surveyPair);

the above call to persist:

JPAHelper db = new JPAHelper();
EntityManager em = db.getEntityManager();
em.getTransaction().begin();
em.persist(surveyPair.getUserSurvey());
em.persist(surveyPair.getSupervisorSurvey());
em.persist(surveyPair);
em.getTransaction().commit();
em.close();

inserts the SurveyPair correctly (foreign IDs column values to UserSurvey and SupervisorSurvey are not null), but the UserSurvey and SupervisorSurvey are inserted with NULL IDs.

Why does this happen? If I debug the code just after the persist method, I can inspect the IDs of the object instances and they result to be actually populated.

guido
  • 18,864
  • 6
  • 70
  • 95
  • Hope this can help: http://stackoverflow.com/questions/9649515/how-to-get-id-of-last-persisted-entity-using-jpa – perissf Nov 14 '12 at 07:02
  • @perissf unfortunately not; the IDs are correctly set in the beans, as I can see during a debug session (I can also see hibernate executing the get_last_insert_id query). But I get a null ID column value. It's also weird that hibernate did not put a primary key over that table column. – guido Nov 14 '12 at 07:37

2 Answers2

1

When we call persist() with an entity JPA creates a new object for database. When you use @GeneratedValue(strategy=GenerationType.AUTO) for id then JPA will responsible for id generation.Since JPA generate id for associated entity at flush time so you need to flush the entityManager instance.

Entity entity = new Entity();
entity.setAddresse("Address");
em.persist(entity);
em.flush();

after flush you will get the id for you entity.

0

I gave up with @OneToOne and converted it in a @ManyToOne relation with an unique=true contrained @JoinColumn:

@XmlElement(name="userSurvey")
@ManyToOne(optional=false)
@JoinColumn(name="`userSurveyId`",unique=true)
private UserSurvey userSurvey;

@XmlElement(name="supervisorSurvey")
@ManyToOne(optional=false)
@JoinColumn(name="`supervisorSurveyId`",unique=true)
private SupervisorSurvey supervisorSurvey;

That way it works; but I will nevertheless accept an alternate answer using @OneToOne if someone comes up with such a solution, because the question is focused on that particular annotation.

guido
  • 18,864
  • 6
  • 70
  • 95