Java Hibernate JPA IdentifierGenerationException:为带有@embeddedid 的类生成空 id

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25295054/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 00:03:42  来源:igfitidea点击:

Hibernate JPA IdentifierGenerationException: null id generated for class with @embeddedid

javahibernatejpahibernate-annotations

提问by Japheth Ongeri - inkalimeva

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

当我尝试使用saveOrUpdate(lesson)hibernate以新的时间段保存课程时会抛出 IdentifierGenerationException

org.hibernate.id.IdentifierGenerationException: null id generated for:class com.trials.domain.Period

org.hibernate.id.IdentifierGenerationException:为:class com.trials.domain.Period 生成了空 ID

The database looks like below (not the real database, just the key tables and columns)

数据库如下所示(不是真正的数据库,只是关键的表和列)

enter image description here

在此处输入图片说明

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.

在 java 休眠模型中,我使用了一个嵌入的 id 作为周期类的主键,然后课程类引用了一个周期。

Period.java

期间.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:

嵌入的 id 只有主键列:

PeriodId.java

周期ID.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

课程.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:

Timeslot 和 Day 实体类都是非常基本的 pojo,它们的 id 使用GenerationType.AUTO. 所以我的问题是:

  1. What causes this IdentifierGenerationException
  2. How to avoid it while keeping the same database model
  1. 是什么导致了这个 IdentifierGenerationException
  2. 如何在保持相同数据库模型的同时避免它

Thanks in advance

提前致谢

采纳答案by Dalton

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.

在 PeriodId 类中并丢弃这些整数。我已经以这种方式完成了类似于您的映射,并且它有效。

回答by Rowanto

On a first glance, You're missing the generated value annotation in the embedded id class.

乍一看,您在嵌入的 id 类中缺少生成的值注释。

@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
}

回答by Petr Osipov

I was able to create the following mapping for my case (scala code) and could totally throw away the @Embeddable class:

我能够为我的案例(scala 代码)创建以下映射,并且可以完全丢弃 @Embeddable 类:

@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
}