【问题标题】:Jpa prepersist callback not called on parent未在父级上调用 Jpa prepersist 回调
【发布时间】:2014-11-21 13:06:42
【问题描述】:

我的代码

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class SiteMessage implements Identifiable{
    @PrePersist
    public void onCreate1(){
        System.out.println("Executed onCreate1");
    }
}

@Entity
@Table(name = "feedback")
public class Feedback extends SiteMessage {
    @PrePersist
    public void onCreate2(){
        System.out.println("Executed onCreate2");
    }
}

当我保存反馈实体时,我希望我会看到:Executed onCreate1 和 Executed onCreate2,但我只看到 Executed onCreate2

我用的是eclipselink v2.5.2

【问题讨论】:

  • 两个表记录都被插入了吗? OTOH,如果我坚持一个子类的实例,那么我希望这个子类的 @PrePersist 方法被调用,而不是超类。毕竟子类是一个完整的实体,它将被持久化到两个表中,但仍然是一个对象。
  • 我的父类中有一个日期字段,我想在数据库中创建新记录时设置当前时间
  • 如果你使用联合继承,它会起作用吗?
  • 是的。当我使用连接继承类型时它可以工作。我创建了一个测试仓库github.com/SunPj/eclipselink-h2-jpa/tree/master

标签: java jpa eclipselink


【解决方案1】:

《精通 Java 持久性 API》一书指出以下内容:

继承回调方法

回调方法可能发生在任何实体或映射的超类上,无论是 抽象的或具体的。规则相当简单。 这是每个 给定事件类型的回调方法将按顺序调用 根据其在层次结构中的位置,首先是最通用的类​​。 因此,如果在我们在图 10-10 中看到的 Employee 层次结构中, Employee 类包含一个名为 PrePersist 的回调方法 checkName() 和 FullTimeEmployee 还包含一个 PrePersist 回调 名为 verifyPension() 的方法,当 PrePersist 事件发生时, checkName() 方法将被调用,然后是 verifyPension() 方法。

因此,如果原始代码中的其他所有内容都正确,您应该会看到 onCreateOne() 和 onCreateTwo() 均按此顺序调用。

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class SiteMessage implements Identifiable{
    @PrePersist
    public void onCreateOne(){
        System.out.println("Executed onCreate1"); //executes first
    }
}

@Entity
@Table(name = "feedback")
public class Feedback extends SiteMessage {
    @PrePersist
    public void onCreateTwo(){
        System.out.println("Executed onCreate2"); //executes second
    }
}

它继续注意以下内容,因此您应该能够完全按照要求进行设置。

我们也可以在 CompanyEmployee 映射的超类上有一个方法 我们希望将其应用于所有子类化它的实体。要是我们 添加一个名为 checkVacation() 的 PrePersist 方法,用于验证 假期结转小于一定金额,将被执行 在 checkName() 之后和 verifyPension() 之前。它变得更有趣 如果我们在 PartTimeEmployee 类上定义一个 checkVacation() 方法 因为兼职员工没有那么多假期。 注释 使用 PrePersist 覆盖的方法会导致 要调用的 PartTimeEmployee.checkVacation() 方法而不是 一个在 CompanyEmployee

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class SiteMessage implements Identifiable{
    @PrePersist
    public void onCreate(){
        System.out.println("Executed onCreate1"); //will not execute
    }
}

@Entity
@Table(name = "feedback")
public class Feedback extends SiteMessage {
    @PrePersist
    public void onCreate(){
        System.out.println("Executed onCreate2"); //will execute
    }
}

【讨论】:

  • 这不是我需要的。我的父类中只需要一个回调,但它不起作用(即使我从子类中删除了回调)。
  • 第一个不是我期望的工作。方法 onCreateOne() 尚未执行。我只见过“Executed onCreate2”
  • 我制作了测试项目以显示 PreCreate 不起作用。 github.com/SunPj/eclipselink-h2-jpa/tree/master
  • 当我将 eclipselink 更改为休眠时,一切正常。我认为这是一个错误
【解决方案2】:

您可以在基本实体(父实体)上使用注解“@MappedSuperClass”。 正如我所展示的:

@MappedSuperclass
public class Base implements Serializable {

    @Id
    private UUID id;

    @PastOrPresent
    private OffsetDateTime createdAt;

    @PastOrPresent
    private OffsetDateTime updatedAt;

    //get/set here

    @PrePersist
    public void prePersist() {
        createdAt = OffsetDateTime.now();
        updatedAt = OffsetDateTime.now();
    }

}

内部类:

@Entity
@HasExtendedValidator
public class Settings extends Base implements Serializable  {
..
}

像魅力一样工作!

【讨论】:

    猜你喜欢
    • 2018-01-09
    • 2021-08-02
    • 1970-01-01
    • 2016-05-24
    • 1970-01-01
    • 1970-01-01
    • 2011-12-01
    • 1970-01-01
    • 2020-01-01
    相关资源
    最近更新 更多