Keep Your Entity Mappings Simple and Efficient

Thorben Janssen
97 Things
Published in
3 min readFeb 26, 2020

The Java Persistence API (JPA) and Hibernate provide you with lots of mappings features which enable you

  • to define simple mappings where your table and domain model look very similar, or
  • to implement complex mappings with significant differences in the structure of both models.

But having the option to use complex mappings doesn’t mean that you should use them. These mappings might be interesting, and some of them might be necessary when working with legacy databases, but they are often the reason for a slow persistence layer that’s hard to maintain.

Keep it simple and similar

The easiest way to create a maintainable, high-performance persistence layer is to keep your entity mappings simple. That means creating a domain model that’s very similar to your table model.

Don’t get me wrong. I’m not telling you that you should never use complex mapping features. Sometimes you might need inheritance hierarchies in your domain model. Or you might need to add SQL snippets to your mappings to implement a custom transformation. But you should be aware of the downsides of such mappings:

  • They create an overhead that slows down your application. Typical examples are entity classes that inherit some of their attributes mappings, default ordering of associations, and the transformation of attribute values. These mappings increase the complexity of the generated SQL statements.
  • Complex mappings that rely on rarely used annotations make your entity classes harder to maintain.
  • Some mappings introduce technical limitations that you might regret later. An example of this is InheritanceType.SINGLE_TABLE mapping. The columns mapped by the subclasses contain lots of null values. This prevents you from using not null constraints to ensure data consistency, and indexes get often ignored.

You can avoid all of this by keeping your mapping simple. The fewer annotations you need to use, the better.

Determine which annotations to use

Simple mapping annotations don’t require you to provide native SQL snippets and don’t hide the structure of the table model. Commonly used examples are:

  • @Entity and @Id to define an entity class and primary key,
  • @Column if you only set its name attribute,
  • @Temporal and @Enumerated to describe the mapping of particular types and
  • @ManyToOne and @OneToOne annotations to model managed associations on the entity that maps the foreign key column.

Annotations like @ManyToMany, @AttributeConverter to use custom type mappings, and @MappedSuperclass to use a very basic inheritance mapping, are also OK to use. They introduce additional complexity, but they have minimal impact on the generated SQL statements.

Other annotations hide the structure of your table model or increase the complexity of the generated SQL statements. That’s why I recommend avoiding them for all persistence layers that need to be fast and scalable. Typical examples are:

  • The @Inheritance annotation enables you to use inheritance in your domain model. Relational table models don’t support this concept, and it requires complex mapping operations.
  • The @Where and @OrderBy annotations exclude elements from an association or define a default order of its elements.

Simple is faster

Always remember to keep your table and your domain model as similar as possible. The easiest way to implement an efficient and maintainable persistence layer is to use as few mapping annotations as possible and to avoid some of the more complex ones.

--

--

Thorben Janssen
97 Things

Independent trainer, author (Hibernate Tips — More than 70 solutions to common Hibernate problems www.hibernate-tips.com), blogger (www.thoughts-on-java.org)