java 未对父级调用JPA预持久回调

yfwxisqw  于 2023-04-19  发布在  Java
关注(0)|答案(3)|浏览(127)

我的准则

@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

f0brbegy

f0brbegy1#

《Mastering the Java persistence API》一书指出了以下内容:
继承回调方法
回调方法可以发生在任何实体或Map的超类上,无论是抽象的还是具体的。规则相当简单。**它是给定事件类型的每个回调方法将根据其在层次结构中的位置按顺序调用,大多数通用类首先。**因此,如果在图10-10所示的Employee层次结构中,Employee类包含名为checkName的PrePersists回调方法(),并且FullTimeEmployee还包含名为verifyPension()的PrePersists回调方法,当PrePersists事件发生时,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
    }
}

它继续说明以下内容,因此您应该能够完全按照需要设置。
我们还可以在CompanyEmployeeMap超类上有一个方法,我们希望将其应用于子类化它的所有实体。()验证假期结转是否小于特定金额,它将在checkName之后执行()和验证之前养老金().如果我们定义一个checkVacation,它会变得更有趣()方法,因为兼职员工没有那么多假期。使用PrePersistt注解重写的方法将导致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
    }
}
bqjvbblv

bqjvbblv2#

你可以在Base实体(Parent)上使用Annotation“@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  {
..
}

像一个魅力工作!

tnkciper

tnkciper3#

根据@Alan Hay和@Dante的回答,如果父类用@MappedSuperclass注解,似乎可以工作。然而,我没有自己验证这一点。
在我的例子中,我不能使用@MappedSuperclass,因为我仍然想使用超类作为@Entity,并且@Entity注解不能与@MappedSuperclass一起工作。
至少在当前的Hibernate版本中,没有@MappedSuperclass的父类的超类不会在Hibernate的内部事件callbackRegistry中注册回调,所以这就是为什么它在这种情况下不起作用。还有另一个选项可以使用:
在父类@Entity上注册@EntityListeners,它也会被所有子类触发。例如:

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@EntityListeners(MyListener.class)
public class SiteMessage implements Identifiable{
   
}

@Entity
@Table(name = "feedback")
public class Feedback extends SiteMessage {
   
}

class MyListener{

    @PrePersist
    public void onCreate(SiteMessage o) {
        System.out.println("Executed onCreate")
    }
}

如果你不能使MyListener足够通用以支持你的所有子类,那么也为那些子类创建特定的Listener(例如MyListener 2)并将它们注册到子类上。

相关问题