At some point in a @ManyToMany relationship I had to add some extra columns in the join table (the middle table).
Here's what Gavin King says in Java Persistence with Hibernate (a notable book on the subject):
Later in that chapter for the first approach (the extra entity for the middle table):
Later in that chapter for the second approach (the collection of components approach):
Naively enough I chose the second approach. Who cares that there's a
hibernate dependency in my JPA data access layer. I already have a few
(a hibernate interceptor).
In this approach I had to use the @CollectionOfElements annotation. @CollectionOfElements
works like that: it maps a collection (set, map, list) of something to
a table. This table has no entity attached to it. It can work with
value types, Strings and @Embeddables. In my case it had to be the @Embeddable.
Let me give you an example - it will clear things up: there are classes
and there are students - two entities. There can be two classes with
many students some of which are the same - so the relationship is @ManyToMany. The extra column in the join table would the grade of the student in that class.
So the approach with the @CollectionOfElements works like that: one of the entities holds the relationship - let it be the class entity - so it has something like that:
Student is a simple entity, no code needed. Let's call the student with the grade an GradedStudent:
That's pretty much it. Seems simple, you would think and straightforward.
BUT IT DOESN'T WORK.
Here's what gets wrong:
- Everytime a class entity gets queried, it's version gets incremented. This makes updating a disconnected entity far more difficult and makes the @Version kind of obsolete.
Solution: none, I couldn't find anything remotely connected to this problem on the net.
- The primary key in the join table (with a name like 'class_gradedstudent') is not the [class_id, student_id] but is [class_id,
student_id, grade]. If you put extra columns in the join table and they
are nullable = false, they would become part of the primary key.
- Cascading fails. You have to create and persist a Student first in order it to become a part of a certain class entity. Even though a GradedStudent is said to cascade a Student.
Solution: none, I tried everything I could think of - no luck. I
couldn't find anything remotely connected to this problem on the net.
Regarding 2: a quotation from the same book:
Well, what if I don't want that? It doesn't say.
So, actually the second approach is not an option.