views:

398

answers:

1

I'm having some problems with inheritance and the @PrePersist annotation. My source code looks like the following:

_the 'base' class with the annotated updateDates() method:

@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();
    }
}

_ now the 'Child' class that should inherit all methods "and annotations" from the base class:

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

If I store/persist instances of the Base class to the database, everything works fine. The dates are getting updated. But now, if I want to persist a child instance, the database throws the following exception:

MySQLIntegrityConstraintViolationException: Column 'CREATIONDATE' cannot be null

So, in my opinion, this is caused because in Child the method "@PrePersist protected void updateDates()" is not called/invoked before persisting the instances to the database.

What is wrong with my code?

+1  A: 

I've tested your code with Hibernate as JPA provider (and HSQLDB). I just made the following change in the base class (because you can't use IDENTIY - the default with HSQLDB and also with MySQL if I'm not wrong - with a TABLE_PER_CLASS strategy1):

@Id
@GeneratedValue(strategy = GenerationType.TABLE)
protected Long id;

With this change, the following test method passes:

@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());
}

So the @PrePersist annotated method gets called in the inherited class.

This begs the question: which JPA provider do you use?

1 see this thread for background on this.

Pascal Thivent