The problem

In my case, I was dealing with a many-to-many relationship that was mapped with the @Many-To-Many annotation. This works fine if the table only contains a foreign key to one part of the relationship and a second foreign key to the other part.

However there were additional attributes to be stored, such as a created date. These were not mapped, and as such not taken into account when generating the SQL statement, causing the database to act up (the mandatory create date column was taken into account in the generated insert statement, causing the database to return an error).

The solution

Vlad Mihalcea has a nice blogpost on this topic. It boils down to this: the relationship itself is a class/entity in its own right, so the next step seemed straight forward.

When starting the refactoring, I noticed the dreaded rippling effect with no end. Meaning I had to update an endless stream of classes to map this relationship properly.

The next best thing

As this is a project on a very tight budget and a strict deadline (no surprise, right?), this was not going to help me. So I resorted to an alternative that I actually was not to fond of.

Spring Data has the @Query annotation for JPA repositories. One of the attributes is nativeQuery, this allows to bypass the idea of mappings and write SQL statements.

As I needed a method to insert new rows, I also had to add the @Modyfing annotation. That way, the entity manager is aware that data will be updated or deleted and can act upon it.

In the end I ended up with the following custom method in my repository:

@Query(nativeQuery=true, value ="insert into M2M_table(FK1, FK2, created) VALUES (:fk1, :fk2, :created)")
public void insertM2M(Long fk1, Long fk2, LocalDateTime created);