2

I have a couple of base classes for my Hibernate entities:

@MappedSuperclass
public abstract class Entity<T> {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private T id;

    public T getId() { return this.id; }
}

@MappedSuperclass
public abstract class TimestampedEntity<T> extends Entity<T> {
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "created_at")
    private Date createdAt;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "updated_at")
    private Date updatedAt;

    // Getters and setters for createdAt and updatedAt....
}

Each entity class obviously extends these base classes and gets the id property and the createdAt and updatedAt properties...

@Entity
public class SomeEntity extends TimestampedEntity<Long> {
    // Insert SomeEntity's fields/getters/setters here. Nothing out of the ordinary.
}

My problem is that when saving a new instance of SomeEntity, Hibernate is ignoring any property values from the superclasses. It will attempt to insert its own value for the id column (which is obviously not in sync with the table's identity column) and attempts to insert nulls for both createdAt and updatedAt even though they've definitely been set.

SomeEntity e = new SomeEntity(/* ... */);
e.setCreatedAt(new Date());
e.setUpdatedAt(new Date());

// Here Hibernate runs an INSERT statement with nulls for both createdAt and updatedAt
// as well as a wildly out of sequence value for id
// I don't think it should be trying to insert id at all, since the GenerationType is IDENTITY
Long id = (Long)session.save(e);

What am I doing wrong here? How can I make Hibernate pick up the property values from the MappedSuperclasses?

mbcrute
  • 1,117
  • 1
  • 11
  • 19

1 Answers1

2

You have those fields declared as private. If that's really what you intend (as opposed to protected or package-protected), move those annotations to the getters.

Having annotations on getters is defined as a hibernate best practice. See: Hibernate Annotation Placement Question

An instance of SomeEntity doesn't actually have the field 'updatedAt' because that field is a private member of its super class. The persistence provider sees that the super class needs columns for those fields, but it also sees that the instantiated concrete class doesn't make use of those columns since the concrete class can't 'see' the field 'updateAt'.

Community
  • 1
  • 1
zmf
  • 9,095
  • 2
  • 26
  • 28