Today was a day of greater insights at work. We (Java guys and our DBA) have been discussing how to optimize database access from our Java application. Of course we use JPA (by OpenJPA).
We came to the conclusion, that we all are great fans of interfaces and separation of concerns, but we failed to apply it when we designed our persistence layer.
In our application, the jpa entities are exact copies of the tables in the database. Currently we do a refactoring of our database design, and this hits the application code hard.
The following steps to enlightenment we climbed today:
- When you access the db by scenario/use case dependent views, you decouple the db design from the java entity design and vice versa. Whenever you change your db design, this goes with 0 effort for the java team.
- JPA is capable of integrating values from several tables in one entity, thus JPA entities work like RW-views. Whenever the db design changes, you (should) only have to adjust the JPA annotations to get it working again.
- Use good old component architecture for your Java/Application layer. Each component owns its own private JPA entities and some specific public transfer objects to send and receive information to and from a component.
- Your private JPA entities hold only necessary information. This holds especially true for relations between entities. If you don’t need a relation in your component, just load it as an ID field instead. This will automatically cut unnecessary eager fetches.
If you have considered this points, also read this article on optimizing the use of JPA by
- eager fetching if you need all members of a collection instead of N+1 selects (you can do this with JQL fetch queries, too!)
- lazy loading if you don’t need related objects.
- JPA pagination instead of java pagination for big result sets.
- load specific columns if you don’t need the whole object.