Official website

Database access in a stateless world

27 Jan 2012

min read

JPA (the Java Persistence API) sometimes does a little too much for its own good. Distinctions between managed and unmanaged entities or between save() and merge() are relevant when most objects stay in memory a long time, and are ‘synchronized’ with the database at different intervals during their lifetime.

In a Play! framework application, persistent data is rarely kept in memory for more than a single request. Hence an entity is going to be saved to the database almost after every time it is modfied. Because this is not the workflow JPA designers had in mind, sometimes JPA gets in the way.

JPA in a stateless world

Your controller receives a JSON message with information about an item. In Play!, you use the id in the JSON message to retrieve the object from the database, then use the information in the JSON message to set the entity’s properties, then save the entity again. This means that you are forced to perform a SELECT just to be able to perform the update which comes after.

The reason is that JPA is designed for frameworks which keep entities floating around in memory longer than the request scope: in that case the problem is supposed to go away, because JPA can do its magic to give the illusion of seamless correspondence between the object graph and the database. Except we know that it’s not always so seamless.

Looking for an alternative

Since Play! avoids storing the application state on the JVM heap and prefers Memcached to enhance database access performance, most of the data entering your application will not be part of any persistence context. Your entities will also be saved to the database or to the cache pretty fast after they have been created. That’s great: we can drop the complexity that derive from the premise that the object graph has its own state to be managed separately by the persistence solution.

Play! applications can benefit from simpler persistence. The persistence layer can be a much thinner abstraction, that would allow to express relational operations in a safe way, but would stay out of the way of session management, except for providing access to the database transaction management features (i.e. some kind of commit() and rollback())

Unfortunately, there are not many Java libraries that fit the bill (although I personally like myBatis). As Play! introduced new thinking in the Java world by moving away from the servlet API, maybe it could also serve as a catalyst for new approaches to dealing with databases in Java (Scala, on the other hand, has got its own share of innovative solutions already).