具有实体继承的@PrePersist

ger*_*rry 7 inheritance jpa

我在继承和@PrePersist注释方面遇到了一些问题.我的源代码如下所示:

_带有注释updateDates()方法的'base'类:

@javax.persistence.Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Base implements Serializable{

    ...

    @Id
    @GeneratedValue
    protected Long id;
    ...
    @Column(nullable=false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date creationDate;
    @Column(nullable=false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date lastModificationDate;
    ...
    public Date getCreationDate() {
        return creationDate;
    }
    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }
    public Date getLastModificationDate() {
        return lastModificationDate;
    }
    public void setLastModificationDate(Date lastModificationDate) {
        this.lastModificationDate = lastModificationDate;
    }
    ...
    @PrePersist
    protected void updateDates() {
      if (creationDate == null) {
        creationDate = new Date();
      }
      lastModificationDate = new Date();
    }
}
Run Code Online (Sandbox Code Playgroud)

_现在应该继承基类中所有方法"和注释"的'Child' 类:

@javax.persistence.Entity
@NamedQueries({
    @NamedQuery(name=Sensor.QUERY_FIND_ALL, query="SELECT s FROM Sensor s")
})
public class Sensor extends Entity {
    ...
    // additional attributes
    @Column(nullable=false)
    protected String value;
    ...
    // additional getters, setters
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果我将Base类的实例存储/持久化到数据库,一切正常.日期正在更新.但是现在,如果我想要持久保存子实例,则数据库会抛出以下异常:

MySQLIntegrityConstraintViolationException: Column 'CREATIONDATE' cannot be null
Run Code Online (Sandbox Code Playgroud)

所以,在我看来,这是因为在Child中,在将实例持久化到数据库之前,不调用/调用方法"@PrePersist protected void updateDates()".

我的代码出了什么问题?

Pas*_*ent 5

我用Hibernate作为JPA提供程序(和HSQLDB)测试了你的代码.我只是在基类中进行了以下更改(因为你不能使用IDENTIY- 默认使用HSQLDB,如果我没有错误也使用MySQL - 使用TABLE_PER_CLASS策略1):

@Id
@GeneratedValue(strategy = GenerationType.TABLE)
protected Long id;
Run Code Online (Sandbox Code Playgroud)

通过此更改,以下测试方法通过:

@Test
public void test_Insert_EntityWithInheritedPrePersist() {
    EntityWithInheritedPrePersist child = new EntityWithInheritedPrePersist();
    child.setValue("test");
    entityManager.persist(child);

    assertEquals(child.getId(), Long.valueOf(1l));
    assertNotNull(child.getCreationDate());
    assertNotNull(child.getLastModificationDate());
}
Run Code Online (Sandbox Code Playgroud)

因此@PrePersist,在继承的类中调用带注释的方法.

这引出了一个问题:你使用哪个JPA提供商?

1有关背景,请参阅此主题.