JPA Entity With Abstract Class Inheritance

13,223

You have several possibilities here.

You did not define a mapping for your superclass. If it is supposed to be a queryable type, you should annotate it with @Entity and you would also need an @Id attribute (this missing @Id attribute is the reason for the error you are getting after adding the @Entity annotation)

If you do not need the abstract superclass to be a queryable entity, but would like to have it's attributes as columns in tables of it's subclasses, you need to annotate it with @MappedSuperclass

If you do not annotate your superclass at all, it is considered to be transient by the provider and is not mapped at all.

EDIT: By the way, you do not have to modify the lastModified value yourself (except you really want to) - you can let the persistence provider do it for you each time you persist the entity with a lifecycle callback:

@PreUpdate
void updateModificationTimestamp() {
 lastModified = System.currentTimeMillis();
}
Share:
13,223
Dobbo
Author by

Dobbo

I am a long time developer. I have programmed a most levels in the application stack from device drivers to GUIs. I love it all. Getting a computer to do stuff it what gets me out of bed on a cold and damp Monday morning, and as I live in England I know about cold and damp Monday mornings!

Updated on August 15, 2022

Comments

  • Dobbo
    Dobbo over 1 year

    I have an abstract class that provides some common functionality that some of the EJB entities which to inherit. One of these is a timestamp column.

    public abstract class AbstractEntity {
    
        ...
        private long lastModified;
        ...
    
        @Column
        public long getLastModified() {
            return lastModified;
        }
    
        public void setLastModified(long ts) {
           lastModified = ts;
        }
    }
    

    and

    @Table
    @Entity
    public class MyEntity extends AbstractEntity {
        ...
        private Long key;
        private String value;
        ...
    
        @Id
        public Long getKey() {
            return key;
        }
    
        public void setKey(Long k) {
            key = k;
        }
    
        @Column
        public String getValue() {
            return value;
        }
    
        public void setValue(String txt) {
            value = txt;
            setLastModified(System.currentTimeMillis());
        }
    }
    

    The issue is that the timestamp column is not being added to the database table. Is there some annotation that needs to be added to AbstractEntity in order for the lastModified fields to be inherited as a column?

    I tried adding @Entity to the AbstractEntity but that caused an exception at deployment.

    org.hibernate.AnnotationException: No identifier specified for entity:
    AbstractEntity
    
  • Dobbo
    Dobbo over 11 years
    Many thank yous Kostha - the @MappedSuperclass annotation was just the solution I was looking for.
  • kostja
    kostja over 11 years
    You're welcome :) There's one more thing I noticed in your code, maybe you will find it useful - see the edit.
  • Dobbo
    Dobbo over 11 years
    Thanks again Kostja - your edit is exactly where I was going. As it happens I do have to modify lastModified myself as (some of) the entity objects are shared with the client and data is transported via XML and JAXB.
  • kostja
    kostja over 11 years
    @Dobbo I see, then you would rather want to know the actual modification time and not the persist time. Makes sense
  • Dobbo
    Dobbo over 11 years
    Yes, modification time is the way I am planning, then a task client side can poll requesting updates since the last poll. I dislike polling, but can't see an alternative given firewalling rules these days. I also plan to mark lastUpdate with the @Version annotation and implement Optimistic Concurrency Control. It looks like the good fit for my client/server relationship. But if you know of a better/alternative solution I welcome suggestions.