JPA implementation patterns: Retrieving entities

Vincent Partington

Last week I talked about how to save an entity. And once we've saved an entity we'd also like to retrieve it. Compared to managing bidirectional associations or saving entities, retrieving entities is actually rather simple. So simple I doubted whether there would be much point in writing this blog ;-) . However we did use a few nice patterns when writing code for this. And I'm interested to hear what patterns you use to retrieve entities. So here is the next instalment in the series on JPA implementation patterns.

Basically, there are two ways to retrieve an entity with JPA:


A Query object can also be created by referring to a named query (using EntityManager.createNamedQuery), or by passing in an SQL query (using one of the three three flavours of EntityManager.createNativeQuery). And while the name implies otherwise, a Query can also be used to execute an update or delete statement.

A named query may seem like a nice way to keep the query with the entities it queries, I've found that not to work out very well. Most queries need parameters to be set with one of the variants of Query.setParameter. Keeping the query and the code that sets these parameters together makes them both easier to understand. That is why I keep them together in the DAO and shy away from using named queries.

A convention I've found to be useful is to differentiate between finding an entity and getting an entity. In the first case null is returned when an entity cannot be found, while in the latter case an exception is thrown. Using the latter method when your code expects an entity to be present prevents NullPointerExceptions from popping up later.

Finding and getting a single entity by id

An implementation of this pattern for the JpaDao base class we discussed a few blogs ago can look like this (I've included the find method for contrast):

public E findById(K id) {
	return entityManager.find(entityClass, id);
}

public E getById(K id) throws EntityNotFoundException {
	E entity = entityManager.find(entityClass, id);
	if (entity == null) {
		throw new EntityNotFoundException(
			"Entity " + entityClass.getName() + " with id " + id + " not found");
	}
	return entity;
}

Of course you'd also need to add this new method to the Dao interface:

E getById(K id);

Finding and getting a single entity with a query

A similar distinction can be made when we use a query to look for a single entity. The findOrderSubmittedAt method below will return null when the entity cannot be found by the query. The getOrderSubmittedAt method throws a NoResultException. Both methods will throw a NonUniqueResultException if more than one result is returned. To keep the getOrderSubmittedAt method consistent with the findById method we could map the NoResultException to an EntityNotFoundException. But since there are both unchecked exceptions, there is no real need.

Since these methods apply only to the Order object, there are a part of the JpaOrderDao:

public Order findOrderSubmittedAt(Date date) throws NonUniqueResultException {
	Query q = entityManager.createQuery(
		"SELECT e FROM " + entityClass.getName() + " e WHERE date = :date_at");
	q.setParameter("date_at", date);
	try {
		return (Order) q.getSingleResult();
	} catch (NoResultException exc) {
		return null;
	}
}

public Order getOrderSubmittedAt(Date date) throws NoResultException, NonUniqueResultException {
	Query q = entityManager.createQuery(
		"SELECT e FROM " + entityClass.getName() + " e WHERE date = :date_at");
	q.setParameter("date_at", date);
	return (Order) q.getSingleResult();
}

Adding the correct methods to the OrderDao interface is left as an exercise for the reader. ;-)

Finding multiple entities with a query

Of course we also want to be able to find more than one entity. In that case I've found there to be no useful distinction between getting and finding. The findOrdersSubmittedSince method just return a list of entities found. That list can contain zero, one or more entities. See the following code:

public List findOrdersSubmittedSince(Date date) {
	Query q = entityManager.createQuery(
			"SELECT e FROM " + entityClass.getName() + " e WHERE date >= :date_since");
	q.setParameter("date_since", date);
	return (List) q.getResultList();
}

Observant readers will note that this method was already present in the first version of the JpaOrderDao.

So while retrieving entities is pretty simple, there are a few patterns you can stick to when implementing finders and getters. Of course I'd be interested to know how you handle this in your code.

P.S. JPA 1.0 does not support it yet, but JPA 2.0 will include a Criteria API. The Criteria API will allow you to dynamically build JPA queries. Criteria queries are more flexible than string queries so you can build them depending on input in a search form. And because you define them using domain objects, they are easier to maintain as references to domain objects get refactored automatically. Unfortunately the Criteria API requires you to refer to your entity's properties by name, so your IDE will not help you when you rename those.

For a list of all the JPA implementation pattern blogs, please refer to the JPA implementation patterns wrap-up.

Comments (16)

  1. Lars Vonk - Reply

    April 3, 2009 at 8:36 pm

    Hi Vincent,

    Problems I have with the findByXXX stuff is that it doesn' t scale well. Especially when you provide some sort of search functionality on different properties. This means you would have to add all kinds of findByThisPropertyAndThatProperty.
    So if you suffer from lots of findByXXX methods and constantly need to add stuff to your dao interface you can apply the specification pattern. Instead of isStatisfiedby a Specification should be able to transform itself to (part of) a where clause.
    This would keep your DAO interface clean: DAO.findBySpecification(Specification). Extra bonus: The relatively small specification classes are easy to test!
    In case of JPA 2.0 or SessionFactory you could use Criteria for this, but that would leak your implementation details to the client code.

  2. Dave - Reply

    April 4, 2009 at 2:06 am

    I'm really appreciating this series of articles...thanks! Can I make a future article request? I'm struggling with persisting/reading BLOBS using JPA (the dreaded OutOfMemoryException that results when a byte[] is used for backing a BLOB and large BLOBS are created ... say, from a file upload). Would love to hear your thoughts in dealing with this ;)

    Keep up the great work.

    Dave

  3. Tom - Reply

    April 4, 2009 at 5:29 pm

    Pretty good series of articles !
    Thanks a lot for your hints and tips.

  4. Dave - Reply

    April 4, 2009 at 6:21 pm

    @Vincent

    "...In case of JPA 2.0 or SessionFactory you could use Criteria for this, but that would leak your implementation details to the client code".

    Sure, but in the interest of "scaling" well, does not the use of Specifications mean that you have to ship all your objects over the wire from the database in order to apply the Specification? At least with the Criteria API, you can let the database doing the selection for you (an operation it's quite optimized at performing). Sure, for small result sets, using Specifications won't impact performance at all. But what about for very large result sets?

  5. Tech Per - Reply

    April 4, 2009 at 8:13 pm

    Great blog entry!

    I was wondering: Do you have any advice or thoughts on how to name or design query methods to support eager loading for different usage scenarios?

    Say, I have a findOrdersSubmittedSince(...) method. And say an Order has OrderLines.

    In one use-case, the application only needs the Order instances. No need to load the OrderLines.

    On another use-case, the application needs to OrderLines too, hence I would like the find method to eager load the relation to OrderLines.

    But I don't want to write two queries.

    And I don't want methods like findOrdersWithOrderLinesLoadedSubmittedSince(...) or the like.

    Any thoughts?

  6. Stg Unholy - Reply

    April 5, 2009 at 3:28 pm

    This is really great articles! And I also struggling with situations, when sometimes You need just Order, and sometimes - Order with all items....The guidelines are really appreciated.

  7. Dave - Reply

    April 5, 2009 at 5:07 pm

    @Lars

    LOL...serves me right for posting *before* actually reading the chapter on Specifications in Evan's DDD book. Turns out that implementing a Specification to return a Criteria object (or SQL string, if you like) to be executed by your domain Repository is perfectly valid, and gets around having to ship your objects across the wire to filter them. So Specs really do mesh well with Repositories (which is explicitly stated in the book). Apologies! (and apologies for calling you Vincent by mistake in the first post LOL).

    Dave

  8. Lars - Reply

    April 5, 2009 at 8:13 pm

    @Dave

    No need to apologise, I am glad you answered your own question :-).

  9. Andrew Phillips - Reply

    April 6, 2009 at 12:18 pm

    @Lars, Dave: In case of JPA 2.0 or SessionFactory you could use Criteria for this, but that would leak your implementation details to the client code.

    I think that depends a little bit on whether you regard the use of a particular Criteria API as an "implementation detail".

    If, for whatever reason, you do decide to add a "generic" find(Criteria) method to your DAO, you'll need to use some kind of Criteria objects. Should you have to reinvent this particular wheel if a suitable implementation already exists?

    To be clear: this is only a question of perspective. If you decide to use the JPA Criteria in your DAO interface definition, you will still force clients to have a dependency on (that part of) JPA, which is something you may want/have to avoid.

    But I think it's perfectly valid to interpret your interface's definition of find as "the client can specify a set of filter criteria, and it is the job of the DAO implementation to interpret these and return the correct results". And then, at least according to me, it's not implementation leakage.

    In practice, of course, it may be difficult to use a certain Criteria API in any implementation other than the "native" one.
    Indeed, in previous projects I have ended up reinventing some of this wheel and writing my own Criteria API, together with a converter that converted "my" criteria to Hibernate criteria, for use in a Hibernate implementation.
    In this case, the reasons were, in fact, less related to enforced Hibernate dependencies. Instead, the key considerations were to

    • use only criteria objects that could be easily and cheaply serialized and constructed in other programming languages and
    • limit the expressiveness of the critiera API up front (i.e. on the client side), rather than returning CriteriaNotSupported-type errors later. We didn't want to allow "A or B", for instance, only "A and B".
  10. Andrew Phillips - Reply

    April 6, 2009 at 12:23 pm

    @Tech: And I don’t want methods like findOrdersWithOrderLinesLoadedSubmittedSince(…) or the like. Any thoughts?

    When we were last faced with this problem, we also decided against findOrdersWithThisAndNotThat-type methods. In fact, we regarded them as violations of the DAO pattern (@Vincent: I'm curious as to what your thoughts on this are).

    In our opinion, a DAO should be tailored to retrieve the information that the application needs, with different methods for different needs. But from a domain model perspective, findOrdersWithThisAndThat and findOrdersWithThisButNotThat return the same information: a collection of Orders meeting some criteria.

    The WithThis... bit thus does not identify a different business need, it is simply a "hint" that only a certain part of the returned object graph is required, and that the rest may be ignored. The usual assumption being that this will lead to a performance improvement.

    But assume that, for some specific implementation, findWithThisButNotThat is actually slower/more memory intensive/more insert favourite performance metric here than findWithThisAndThat. Would it ever be called?

    Our approach was to (attempt to) model what we felt the WithThisAndThat actually represents: a suggestion to the implementation that only certain properties are required, and others may be ignored if this is likely to improve performance. We called it a FetchModel and allowed the user to specify FetchTypes (very similar to Hibernate's FetchModels) for properties.

    For those DAO methods for which this was relevant, we then had an overloaded method (let's defer the discussion about the evils of overloading for a minute)

      /** Uses the default fetch model */
      Collection findOrdersSubmittedSince(Date date);
    
      Collection findOrdersSubmittedSince(Date date, FetchModel fetchModel);
    

    where, in the case of your example, you would specify something like

      FetchModel noOrderLinesFetchModel = new FetchModel(Order.class);
      noOrderLinesFetchModel.setFetchType("orderLines", FetchType.NONE);
    

    It's then down to the implementation to interpret the fetch model, if desired.

    Writing the code to actually implement a fetch model specification for a specific ORM framework is non-trivial, but if done with a bit of thought it can easily be reused.

  11. Vincent Partington - Reply

    April 6, 2009 at 7:03 pm

    @Lars: I don't really have much to add on the Criteria thing after the comments by Dave and Andrew. :-) I guess it depends on what you use your DAO's for, how flexible you want them to be.

    In the app we're building we know up front the kind of queries we want to do (no search forms), so having findByXXX methods make sense. They are lot more expressive than having the client build some kind of specification object. Be it JPA Criteria or your own class.

    On the other hand if your app needs to support all kinds of ad hoc queries, such a mechanism makes sense.

  12. Vincent Partington - Reply

    April 6, 2009 at 7:12 pm

    @Tech, Andrew: I think Andrew's suggestion seem pretty solid. I can see why having findOrdersWithOrderLinesLoadedSubmittedSince(…) methods would seem to violate the DAO pattern, but since I am not that much of a purist, I am not that much against them. ;-)

    I think I actually prefer them over having an extra (defaulted) argument that specifies the fetch strategy. That smells too much like the Flag Argument I've learned to abhor since reading Clean Code and Implementation Patterns.

    In fact since reading those books I've moved towards writing more shorter focused methods with descriptive (and therefore somtimes long) names instead of writing "clever" methods that can do all kinds of stuff when passed the right arguments. I guess that is why I'm not too enthusiastic about Lars' criteria/specification suggestion.

  13. Tech Per - Reply

    April 6, 2009 at 7:47 pm

    Thanks for the viewpoints on methods for selecting for a use case. The FetchModel is interesting.

  14. [...] Retrieving entities [...]

  15. Peter Kovacs - Reply

    August 8, 2009 at 2:40 pm

    @Dave: "implementing a Specification to return a Criteria object"

    But this wouldn't be Specifiation pattern any more, would it be? Based on the article referenced by Lars, in the center of the Specification pattern there is an object which decides whether a domain object satisfies some condition(s) or not. In what you suggest, the decision is made outside the Specification, so I am not sure if this is still the same pattern. (I assume that by "Criteria object", you mean a QueryDefinition object.)

  16. JPA Implementation Patterns | Upthrust - Reply

    January 30, 2010 at 12:29 pm

    [...] Retrieving Entities [...]

Add a Comment