I am having trouble mapping my database domain model to the program entities in one case where the entity is essentially a join table (a period) which combines two other entities (a timeslot and a day). Another entity (a lesson) then has a reference to this period entity, determining when it occurs.
When I try to save a lesson with a new period using saveOrUpdate(lesson) hibernate throws an IdentifierGenerationException
org.hibernate.id.IdentifierGenerationException: null id generated for:class com.trials.domain.Period
The database looks like below (not the real database, just the key tables and columns)

In the java hibernate model, I have used an embedded id for the primary key of the period class and the lesson class then has a reference to a period.
Period.java
@Entity @Table(name = "period") public class Period{ @EmbeddedId private PeriodId periodId; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "day_idday", nullable = false, insertable = false, updatable = false) private Day day; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "timeslot_idtimeslot", nullable = false, insertable = false, updatable = false) private Timeslot timeslot; //constructors, getters, setters, hashcode, and equals } And the embedded id just has the primary key columns:
PeriodId.java
@Embeddable public class PeriodId implements Serializable { @Column(name = "timeslot_idtimeslot") private int timeslotId; @Column(name = "day_idday") private int dayId; //constructors, getters, setters, hashcode, and equals } Then there is the lesson class that uses the period defined as:
Lesson.java
@Entity @Table(name = "lesson") public class Lesson { @Id @Column(name = "idlesson") private int lessonId; @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumns({@JoinColumn(name = "period_timeslot_idtimeslot", nullable = false, updatable = false), @JoinColumn(name = "period_day_idday", nullable = false, updatable = false)}) private Period period; //constructors, getters, setters, hashcode, and equals } The Timeslot and Day entity classes are both very basic pojos, and their ids use GenerationType.AUTO. So my problems are:
- What causes this IdentifierGenerationException
- How to avoid it while keeping the same database model
Thanks in advance
23 Answers
Put those guys
@ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "day_idday", nullable = false, insertable = false, updatable = false) private Day day; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "timeslot_idtimeslot", nullable = false, insertable = false, updatable = false) private Timeslot timeslot; inside the PeriodId class and throw away those ints. I have done a mapping similar to yours this way and it works.
4I was able to create the following mapping for my case (scala code) and could totally throw away the @Embeddable class:
@Entity @Table(name = "payment_order_item", schema = "pg") @IdClass(classOf[PaymentOrderItem]) final class PaymentOrderItem extends Serializable{ @Id @ManyToOne @JoinColumn(name = "order_item_id", referencedColumnName = "id") var orderItem: OrderItem = _ @Id @ManyToOne @JoinColumn(name = "payment_id", referencedColumnName = "id") var payment: Payment = _ } So the following should work for you then
@Entity @Table(name = "period") @IdClass(Period.class) public class Period extends Serializable{ @Id @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "day_idday", referencedColumnName = "id", nullable = false) private Day day; @Id @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "timeslot_idtimeslot", referencedColumnName = "id", nullable = false) private Timeslot timeslot; //constructors, getters, setters, hashcode, and equals } On a first glance, You're missing the generated value annotation in the embedded id class.
@Embeddable public class PeriodId implements Serializable { @GeneratedValue @Column(name = "timeslot_idtimeslot") private int timeslotId; @GeneratedValue @Column(name = "day_idday") private int dayId; //constructors, getters, setters, hashcode, and equals } 0