Effective pattern for data access with JPA

Posted: May 5th, 2011 | Author: | 4 Comments »

Since Java EE 6 is out, many of patterns and blueprints that were described with J2EE are deprecated. The main reason is due to the new architecture offers new components that simplify the development. One of these components is EntityManager, which can be consider as the implementation of DAO pattern. This object provides us common functions to operate with our model in a relational database. Some of these functions are save, retrieve, update and delete entities, that is, tipical CRUD operations.

Where is the problem?

It all depends on how you layerizer your application. Many of code that you can see about data access with JPA uses the EntityManager injected directly in the business objects or web controllers. In my opinion, with this approach couples too much the business logic with the technology used in the persistence layer. Think for a moment that an entire application developed by using this way has serious performance problems and the reponsible determines to move the persistence layer to NoSql approach, this decision would mean having to change this reference from every class. As you can see, it would mean an unbelievable effort.

Creating the indirection

First of all, the idea of using a facade to access JPA looks mandatory if we want to uncouple the technology with the data access. In this line, the next interface is proposed:

public interface PersistenceService<K, E> {

	E save(E entity);

	E update(E entity);

	void remove(E entity);

	E findById(K id);

	List<E> findAll();

	Long getTotalResult();
}

By using Java Generics this interface provides the common operation with entities. Each class that implements this interface have to indicate what the type of entity it manages E and the type of identificator K. Obviously, this class will have to implement the methods too :D

Now, we have to define abstract classes either for the entities or for persistence services. These abstract classes help us to put in the same location all the common code, leaving the concrete classes that they implements only the specific code.

In JPA to model entities, we need a classes with Entity annotation, but there is some code that is mandatory in each entity, for example the identificator. In addition, we use named queries for those queries that are typical in any scenario, so the entities need the constants for these named queries. The abstract entity is as follow:

@MappedSuperclass
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class AbstractEntity implements Serializable {

    public static final String FIND_ALL = "Entity.findAll";

    public static final String TOTAL_RESULT = "Entity.totalResult";

    private static final long serialVersionUID = 1L;

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

    // Getters and Setters
}

With @MappedSuperclass and @Inheritance we indicates that this class doesn’t have to be mapped to a table and the constants will be used in the named queries. Due to JPA 2.0 doesn’t allow inheritance for named queries, these two queries will be defined in each specific entity.

Now, the code for the abstract persistence service. This class performs the CRUD operations through the EntityManager. The code is:

public abstract class AbstractJPAPersistenceService<K, E extends AbstractEntity> implements PersistenceService<K, E> {

    protected Class<E> entityClass;

    @PersistenceContext
    protected EntityManager em;

    @PostConstruct
    public void init() {
        ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
        this.entityClass = (Class<E>) genericSuperclass.getActualTypeArguments()[1];
    }

    @Override
    public E save(final E entity) {
        em.persist(entity);
        return entity;
    }

    @Override
    public E update(final E entity) {
        return em.merge(entity);
    }

    @Override
    public void remove(final E entity) {
        em.remove(em.merge(entity));
    }

    @Override
    public E findById(final K id) {
        return em.find(entityClass, id);
    }

    @Override
    public List<E> findAll() {
        return em.createNamedQuery(AbstractEntity.FIND_ALL).getResultList();
    }

    @Override
    public Long getTotalResult() {
        return (Long) em.createNamedQuery(AbstractEntity.TOTAL_RESULT).getSingleResult();
    }

}

With this class, each subclass just implements its specific method for queries. Perhaps, the most important part is in the method init() where the entity class is created by using reflection through generic values. Due to the idea is to expose the persistence services as EJB, this method is annotated with @PostConstruct that is called each time its subclass is injected. Furthermore, the queries are implemented with the constants declared in the AbstractEntity, the query will be defined in the specific entity.

Implementing an example

Ok, the skeleton for persistence services is ready, just need to use in a real scenario. In this case, to show how easy it is to use this “pattern”, the example is about the Book entity.

@Entity
@NamedQueries({
    @NamedQuery(name = Book.FIND_ALL, query = "select b from Book b"),
    @NamedQuery(name = Book.TOTAL_RESULT, query = "select count(b) from Book b"),
    @NamedQuery(name = Book.FIND_BY_TITLE, query = "select b from Book b where b.title = :title"),
    @NamedQuery(name = Book.FIND_BY_ISBN, query = "select b from Book b where b.isbn = :isbn")
})
public class Book extends AbstractEntity {

    public static final String FIND_BY_TITLE = "Book.findByTitle";

    public static final String FIND_BY_ISBN = "Book.findByISBN";

    private String title;

    private String description;

    private String isbn;

    // Getters and Setters

The code is quite basic: declaration of attributes (fields in the table), specific queries and named queries with @NamedQueries.

Finally, the implementation of PersistenceService to manage books is as follow:

@Stateless
public class BookPersistenceService extends AbstractJPAPersistenceService<Long, Book> {

    public List<Book> findByTitle(String title) {
        return em.createNamedQuery(Book.FIND_BY_TITLE).setParameter("title", title).getResultList();
    }

    public List<Book> findByISBN(String isbn) {
        return em.createNamedQuery(Book.FIND_BY_ISBN).setParameter("isbn", isbn).getResultList();
    }
}

As you can see, the code is very light because the complexity is in AbstractJPAPersistenceService. To use this service, just inject it in your business logic.


Tags: , , , ,

4 Comments on “Effective pattern for data access with JPA”

  1. 1 Oliver Gierke said at 3:38 pm on May 7th, 2011:

    Hi Eduardo,

    great blog post. There’s definitely a bit of room for improvement when working with queries in JPA. You might be interested in the Spring Data JPA project that to some extend is an implementation of the ideas you provided here. For your example, you’d simply need an interface declaring finder methods to execute the query:

    public interface BookRepository extends JpaRepository {

    List findByTitle(String title);
    List findByISBN(String isbn);
    }

    In a Spring context you could use a simple XML namespace element to let Spring discover your interface build a proxy and automatically derives the queries from the methods you declared.

    Although we Spring under the hoods, it’s not tied to be used in a Spring container only. You can also create instances for the interface just shown programatically:

    RepositoryFactorySupport factory = new JpaRepositoryFactory(entityManager);
    BookRepository repository = factory.getRepository(BookRepository.class);

    This should be easily wrappable into some CDI configuration class so that you can use stuff as simple helper library inside a JavaEE context as well.

    This blog post [1] documents how much code you can save by this approach, where as this one [2] is covering advanced topics like improving usability of the Criteria API and integration with the type safe query library Querydsl.

    Cheers,
    Ollie

    [1] http://blog.springsource.com/2011/02/10/getting-started-with-spring-data-jpa/
    [2] http://blog.springsource.com/2011/04/26/advanced-spring-data-jpa-specifications-and-querydsl

  2. 2 Eduardo Fernández León said at 9:19 pm on May 7th, 2011:

    Hi Oliver,

    Thanks for your comment :) ,

    I am not familiar with Spring Data, but from what I read in your articles both approaches are similar (but with different implementations). I liked the usage of @Query in the interface, in [1] there is something like these by using Weld Extensions.

    Regards,
    Edu.

    [1] http://docs.jboss.org/weld/extensions/reference/1.0.0.Beta1/en-US/html_single/#servicehandler

  3. 3 tollwood said at 12:54 pm on April 14th, 2012:

    When using the abstract Entity Class in two entities I get an error message “Duplicate query named “Entity.findAll” defined in this persistence unit”

    What can I do about it?

  4. 4 Wayne Riesterer said at 12:42 am on January 6th, 2013:

    Hi Eduardo :)

    Great post. I have been searching for a JPA pattern for a while and this is just what I was looking for.

    I tried out this code, but the entities are not being persisted in the database.

    I have other entities that are being persisted fine, just not when using this pattern.

    The table gets created in MySQL and the ID field is also created, but none of the other fields.

    Could this be something to do with the PostConstruct method?

    When I build the application, I see a warning that states “AbstractJPAPersistenceService.java uses unchecked or unsafe operations”. Could this have something to do with it.

    All the best – Wayne


Leave a Reply