ManyToOne

A ManyToOne relationship in Java is where the source object has an attribute that references another object, the target object. I.e. the rather typical Java case that one object holds a reference to another object. A ManyToOne relationship can be specified unidirectional. However, it is typical that the target object has the inverse relationship specified back to the source object. This would be a OneToMany relationship specification in the target object. 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.
In JPA a ManyToOne relationship is specified through the @ManyToOne annotation or the <many-to-one> element. A @ManyToOne annotation is typically accompanied by a @JoinColumn annotation. The @JoinColumn annotation specifies how the relationship should be mapped to (expressed in) the database. The @JoinColumn defines the name of the foreign key column (@JoinColumn(name = "...")) in the source object that should be used to find (join) the target object.
If the reverse OneToMany relationship is specified in the target object, then the @OneToMany annotation in the target object must contain a mappedBy attribute to define this inverse relation.
JPA also defines a OneToOne relationship, which is similar to a ManyToOne relationship, except that the inverse relationship (if it were defined) is a OneToOne relationship. The main difference between a OneToOne and a ManyToOne relationship in JPA is that a ManyToOne always contains a foreign key from the source object's table to the target object's table, whereas a OneToOne relationship the foreign key may either be in the source object's table or the target object's table.
Example of a ManyToOne relationship database
EMPLOYEE (table)
| EMP_ID | FIRSTNAME | LASTNAME | SALARY | MANAGER_ID |
| 1 | Bob | Way | 50000 | 2 |
| 2 | Sarah | Smith | 75000 | null |
PHONE (table)
| ID | TYPE | AREA_CODE | P_NUMBER | OWNER_ID |
| 1 | home | 613 | 792-0000 | 1 |
| 2 | work | 613 | 896-1234 | 1 |
| 3 | work | 416 | 123-4444 | 2 |
Example of a ManyToOne relationship annotations
@Entity
public class Phone {
@Id
private long id;
...
// Specifies the PHONE table does not contain an owner column, but
// an OWNER_ID column with a foreign key. And creates a join to
// lazily fetch the owner
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="OWNER_ID")
private Employee owner;
...
}
// Specification of the reverse OneToMany relationship in Employee
@Entity
public class Employee {
@Id
private long emp_id;
...
// The 'mappedBy = "owner"' attribute specifies that
// the 'private Employee owner;' field in Phone owns the
// relationship (i.e. contains the foreign key for the query to
// find all phones for an employee.)
@OneToMany(mappedBy = "owner")
private List<Phone> phones;
...
Example of a ManyToOne relationship XML
<entity name="Phone" class="org.acme.Phone" access="FIELD">
<attributes>
<id name="id"/>
<many-to-one name="owner" fetch="LAZY">
<join-column name="OWNER_ID"/>
</many-to-one>
</attributes>
</entity>
See Also
Common Problems
Foreign key is also part of the primary key.
Foreign key is also mapped as a basic.
- If you use the same field in two different mappings, you typically require to make one of them read-only using
insertable, updatable = false. - See Target Foreign Keys, Primary Key Join Columns, Cascade Primary Keys.
Constraint error on insert.
- This typically occurs because you have incorrectly mapped the foreign key in a
OneToOnerelationship.
- It can also occur if your JPA provider does not support referential integrity, or does not resolve bi-directional constraints. In this case you may either need to remove the constraint, or use
EntityManagerflush()to ensure the order your objects are written in.
Foreign key value is null
- Ensure you set the value of the object's
OneToOne, if theOneToOneis part of a bi-directionalOneToManyrelationship, ensure you set the object'sOneToOnewhen adding an object to theOneToMany, JPA does not maintain bi-directional relationships for you. - Also check that you defined the
JoinColumncorrectly, ensure you did not setinsertable, updateable = falseor use aPrimaryKeyJoinColumn.
Advanced
Target Foreign Keys, Primary Key Join Columns, Cascade Primary Keys
In complex data models it may be required to use a target foreign key, or read-only JoinColumn in mapping a ManyToOne if the foreign key/JoinColumn is shared with other ManyToOne or Basic mappings.
See, Target Foreign Keys, Primary Key Join Columns, Cascade Primary Keys