In this post, we will explore a very common Hibernate error, namely a MappingException caused by missing annotations on the Entity getters and fields.

If you would like to have a solid knowledge foundation about JPA and Hibernate, then I strongly recommend reading the book “High-Performance Java Persistence (click to check current price on Amazon)” by Vlad Mihalcea. The book focuses on JPA and working with relational databases in order to cleanly develop applications that utilize a persistence backend. The author is one of the developers of the Hibernate framework which gives it a high authority on the topic.

The error

Let us check the following stack trace as an example:

[org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]

: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could not determine type for: java.util.List, at table: bank_account, for columns:

[org.hibernate.mapping.Column(credit_transactions)]

Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Could not determine type for: java.util.List, at table: bank_account, for columns: [org.hibernate.mapping.Column(credit_transactions)] Caused by: org.hibernate.MappingException: Could not determine type for: java.util.List, at table: bank_account, for columns: [org.hibernate.mapping.Column(credit_transactions)]

In the next section, we will display the faulty implementation that caused the error above. If you would like to skip to the solution, then please use the table of contents on the top of this post.

The example implementation

Now let us take a look at the code. The implementation contains two entities. The first entity is the bank account entity. The second entity is the transaction entity. Each bank account has two many-to-one relationships with the transaction table. A bank account has a list of transactions where it is credited, and a list of transactions where it its debited.

The problem cause

Sadly the information in the stacktrace is not very straightforward. It is telling us that the mapping between the Bank account and the Transaction table for the “credit_transactions” relationship is not correct. Hibernate does not understand the “credit_transactions” field.

The issue is that we have added annotations in the BankAccount entity on the fields and the getters. Notice that we added the @Id and @GeneratedValue annotations on the id field in the BankAccount entity. However, we added the @ManyToOne annotation for our relationship on the getters. If we add the @Id annotation on the getter and the @ManyToOne annotation on the field, then we will get the same error. This means that hibernate will consider only the annotations that are set on the same side as the @Id annotation. So if you add the @Id annotation on a field, then only field annotations will be considered. If the @Id annotation is set on the getter, then only annotations on the getters will be considered.

Adding the annotations on the entity fields is called “Field” access type. Adding the annotations on the entity getters is called “Property” access type. You can override JPA’s default behavior by setting the access type property of the entity.

Solution A

There are two ways to fix such an issue.  First, you will need to have the annotations on either the getters or the fields, but not both.  So, our bank account class would look as follows:

Solution B

While unlikely, it may sometimes be not possible to have the annotations on just one side. For example, if your entity is inheriting from a super class. In this case, you will have to override the annotations of the super class and specifically set the access type depending on which annotations we want to be effective. Let’s say that the superclass uses “field” annotations. Then we can write getters for the fields in the super and subclass and set the access type to “Property”: