【问题标题】:Hibernate JPA IdentifierGenerationException: null id generated for class with @embeddedidHibernate JPA IdentifierGenerationException:为具有@embeddedid 的类生成空ID
【发布时间】:2014-08-13 19:58:20
【问题描述】:

在一种情况下,我在将我的数据库域模型映射到程序实体时遇到问题,其中实体本质上是一个连接表(一个周期),它结合了其他两个实体(一个时间段和一天)。然后另一个实体(一课)引用了这个时期实体,确定它何时发生。

当我尝试使用 saveOrUpdate(lesson) 保存带有新时期的课程时,hibernate 会抛出 IdentifierGenerationException

org.hibernate.id.IdentifierGenerationException: null id 为:class com.trials.domain.Period 生成

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

在 java hibernate 模型中,我使用了一个嵌入的 id 作为 period 类的主键,然后课程类引用了一个 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
}

而嵌入的id只有主键列:

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
}

然后是使用句号定义为的课程类:

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
}

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

  1. 导致此 IdentifierGenerationException 的原因
  2. 如何在保持相同数据库模型的同时避免这种情况

提前致谢

【问题讨论】:

标签: java hibernate jpa hibernate-annotations


【解决方案1】:

把那些家伙放上去

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

在 PeriodId 类中并丢弃这些整数。我以这种方式完成了与您类似的映射,并且可以正常工作。

【讨论】:

  • 好的,我在 PeriodId 类中做了这个,并在 Period 类中标记了原始属性@transient。然后委托 period 类中的 getter 和 setter 从嵌入的 periodId 中设置和获取它们的值
  • 我尝试了你的方法,但现在我得到了数据截断:第 1 行的列 'dalekComponent' 的数据太长。
  • 你能解释一下“扔掉那些整数”是什么意思吗?我是否保留Lesson 中的TimeslotDay 并删除PeriodId 中的int Ids? @Transient 的使用方法是什么?如果我将它们移到 PeriodId,哪个属性将是瞬态的?
  • @MohammedIdris 原始帖子中的整数。
【解决方案2】:

我能够为我的案例(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 = _
}

那么下面的内容应该对你有用

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

【讨论】:

    【解决方案3】:

    乍一看, 您在嵌入的 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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多