Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA doesn't support interfaces well..implications?

Tags:

java

jpa

I was going through some posts in Stackoverflow on JPA and I read multiple places that JPA does not support interfaces. Can someone please share what it means in a real-world project. Does this mean we cannot annotate the interface?

like image 506
Aravind Yarram Avatar asked Nov 17 '10 13:11

Aravind Yarram


2 Answers

What this means is that you cannot map (annotate) or query on an inferface. You can only query @Entity classes, and these can only be placed on real classes, not interfaces. Normally this is not an issue, an interface has no state, so is not something that is really relevant to persistence most of the time. You can still use interfaces in your model, you just can't map them directly.

If you have a relationship that uses an interface type, you just need to set the targetEntity to the implementation class. If you have multiple implementers and can't make them share inheritance then you need to get more creative. Some JPA providers such as EclipseLink have support for interfaces.

See, http://en.wikibooks.org/wiki/Java_Persistence/Advanced_Topics#Interfaces

like image 138
James Avatar answered Sep 20 '22 23:09

James


In JPA, use @MappedSuperclass for inheritance, annotate abstract classes, not interfaces.

I tend to use common base classes for all my entities in a given project:

@MappedSuperclass
public abstract class BaseEntity implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
}

Now let's say that some of my entities have additional behavior in common: automatically updated timestamps for createdDate and updatedDate

@MappedSuperclass
public abstract class ExtendedEntity extends BaseEntity{

    @Temporal(TemporalType.TIMESTAMP)
    private Date createdDate;

    @Temporal(TemporalType.TIMESTAMP)
    private Date updatedDate;

    @PrePersist
    protected void creationTimeStamp(){
        createdDate = new Date();
        this.updateTimeStamp();
    }

    @PreUpdate
    protected void updateTimeStamp(){
        updatedDate = new Date();
    }

}

Now, some of my entities extend BaseEntity directly, and others extend ExtendedEntity (if they need timestamps).

You can also configure the way the inheritance is modeled:

  • A single table per class hierarchy
  • A table per concrete entity class (default)
  • A “join” strategy, whereby fields or properties that are specific to a subclass are mapped to a different table than the fields or properties that are common to the parent class

BTW: I think the choice not to support interfaces is a good one. Interfaces are designed to model behavior, not state. JPA is about managing state, not behavior, so the two concepts don't fit together.

And in cases where you think you need multiple inheritance, perhaps @Embeddable is the solution

like image 20
Sean Patrick Floyd Avatar answered Sep 21 '22 23:09

Sean Patrick Floyd