Java Persistence/ManyToMany

=ManyToMany=

A  relationship in Java is where the source object has an attribute that stores a collection of target objects and (if) those target objects had the inverse relationship back to the source object it would also be a   relationship. All relationships in Java and JPA are unidirectional, in that if a source object references a target object there is no guarantee that the target object also has a relationship to the source object. This is different than a relational database, in which relationships are defined through foreign keys and querying such that the inverse query always exists.

JPA also defines a  relationship, which is similar to a   relationship except that the inverse relationship (if it were defined) is a   relationship. The main difference between a  and a   relationship in JPA is that a   always makes use of a intermediate relational join table to store the relationship, where as a   can either use a join table, or a foreign key in target object's table referencing the source object table's primary key.

In JPA a  relationship is defined through the   annotation or the   element.

All  relationships require a. The  is defined using the   annotation and   XML element. The  defines a foreign key to the source object's primary key, and a foreign key to the target object's primary key. Normally the primary key of the  is the combination of both foreign keys.

Example of a ManyToMany relationship database
EMPLOYEE (table)

EMP_PROJ (table)

PROJECT (table)

Bi-directional Many to Many
Although a  relationship is always bi-directional on the database, the object model can choose if it will be mapped in both directions, and in which direction it will be mapped in. If you choose to map the relationship in both directions, then one direction must be defined as the owner and the other must use the  attribute to define its mapping. This also avoids having to duplicate the  information in both places.

If the  is not used, then the persistence provider will assume there are two independent relationships, and you will end up getting duplicate rows inserted into the join table. If you have a conceptual bi-directional relationship, but have two different join tables in the database, then you must not use the, as you need to maintain two independent tables.

As with all bi-directional relationships it is your object model's and application's responsibility to maintain the relationship in both direction. There is no magic in JPA, if you add or remove to one side of the collection, you must also add or remove from the other side, see object corruption. Technically the database will be updated correctly if you only add/remove from the owning side of the relationship, but then your object model will be out of synch, which can cause issues.

Object not in collection after refresh.

 * If you have a bi-directional  relationship, ensure that you add to both sides of the relationship.
 * See Object corruption.

Additional columns in join table.

 * See Mapping a Join Table with Additional Columns

Duplicate rows inserted into the join table.

 * If you have a bidirectional  relationship, you must use   on one side of the relationship, otherwise it will be assumed to be two different relationships and you will get duplicate rows inserted into the join table.

=Advanced=

Mapping a Join Table with Additional Columns
A frequent problem is that two classes have a  relationship, but the relational join table has additional data. For example if  has a   with   but the PROJ_EMP join table also has an   column. In this case the best solution is to create a class that models the join table. So a  class would be created. It would have a  to   and , and attributes for the additional data. and  would have a   to the. Some JPA providers also provide additional support for mapping to join tables with additional data.

Unfortunately mapping this type of model becomes more complicated in JPA because it requires a composite primary key. The association object's  is composed of the   and   ids. The JPA 1.0 spec does not allow an  to be used on a   so the association class must have two duplicate attributes to also store the ids, and use an , these duplicate attributes must be kept in synch with the   attributes. Some JPA providers may allow a  to be part of an , so this may be simpler with some JPA providers. To make your life simpler, I would recommend adding a generated  attribute to the association class. This will give the object a simpler  and not require duplicating the   and   ids.

This same pattern can be used no matter what the additional data in the join table is. Another usage is if you have a  relationship between two objects, with a third unrelated object or data representing the   key. The JPA spec requires that the  key be an attribute of the   value, so the association object pattern can be used to model the relationship.

If the additional data in the join table is only required on the database and not used in Java, such as auditing information, it may also be possible to use database triggers to automatically set the data.

Example join table association object database
EMPLOYEE (table)

PROJ_EMP (table)

PROJECT (table)

Example join table association object annotations
http://giannigar.wordpress.com/2009/09/04/mapping-a-many-to-many-join-table-with-extra-column-using-jpa/
 * If the given examples won't suit your expectations, try the solution indicated in this link:

/Mapping