The OneToMany and ManyToOne annotations are two major JPA annotations that are used for defining two different kinds of associations. The OneToMany annotation define a many-valued association with one-to-many multiplicity, whereas the ManyToOne annotation defines a single-valued association to another entity that has many-to-one multiplicity. The Multiplicity concept seems ambiguous, but it simply tells you the maximum and minimum allowed members of the set.
It is a UML design concept for defining the association relationship, in one-to-many case, it indicates that one class of the association makes a reference for many classes at the other end. But in many-to-one, it indicates that one or more classes of the association makes a reference for one class at the other end. Let’s define a class A and list of classes of B, if we are talking about OneToMany association between A & list of B, that’s mean the class A has a reference for list of classes of B or in other words, class A has a set of references of B. However, in case we are talking about ManyToOne association between A & list of B, that’s mean the list of class B has a reference of class A, or in other words each class in the list of B has a reference of class A.
This tutorial should clarify everything you would to learn about using of OneToMany and ManyToOne annotations.
Prerequiste for Using OneToMany and ManyToOne Annotation
To be able to use a OneToMany and ManyToOne annotations, you should have a look into those steps that required for installing the JPA implementation. (See EclipseLink – Installation or EclipseLink – Maven – Installation).
The using of OneToMany and ManyToOne annotations requires understanding of anatomy of @OneToMany, @ManyToOne and @JoinColumn (See anatomy of @JoinColumn with @OneToOne).
Anatomy of @OneToMany Annotation
- Target: fields (Including property get methods)
- Uses: @OneToMany
- Arguments: The @OneToMany annotation takes multiple arguments when it used and these are:
- targetEntity (Optional): It is used to determine the entity class that is the target of the association.
- cascade (Optional): It is used to determine the operations that must be cascaded to the target of the association.
- fetch (Optional): It is used to determine whether the association should be Lazily loaded or must be eagerly fetched. The EAGER strategy is a requirement on the persistence provider runtime that the associated entity must be eagerly fetched. The LAZILY strategy is just a hint to the persistence provider runtime.
- optional (Optional): It is used to determine whether the association is optional. If set to false then a non-null must be always exist.
- mappedBy (Optional): The field that owns the relationship. Required unless the relationship is unidirctional.
Anatomy of @ManyToOne Annotation
- Target: fields (Including property get methods)
- Uses: @ManyToOne
- Arguments: The @ManyToOne annotation takes multiple arguments when it used and these are:
- targetEntity (Optional): It is used to determine the entity class that is the target of the association.
- cascade (Optional): It is used to determine the operations that must be cascaded to the target of the association.
- fetch (Optional): It is used to determine whether the association should be Lazily loaded or must be eagerly fetched. The EAGER strategy is a requirement on the persistence provider runtime that the associated entity must be eagerly fetched. The LAZILY strategy is just a hint to the persistence provider runtime.
- optional (Optional): It is used to determine whether the association is optional. If set to false then a non-null must be always exist.
@ManyToOne Applies Unidirectional Association for the OneToMany Relationship
Let’s overview the previous tutorial that introduce the elements being used at the example here; Employee is an entity, associated with an Address with a OneToOne relationship. If you’ve not look it before, follow @OneToOne Tutorial.
Before any further discussion for @ManyToOne association, let’s see the database analysis required to achieve such that relation.
In this tutorial, we are going to establish a new association between Employee and Phones, in that list of phones might be associated with one and only one instance of employee. If you’ve looked at the (Employee-Phone) from a business perspective and from a phone angle of view, you should be able to identify that the Phone has a relation of ManyToOne with the employee; many phones associated with one employee. Meanwhile, if you’ve looked at the (Employee-Phone) from an Employee angle of view, you should be able to identify that the employee has a list of phones. See the figure 1.1. for more clarification of how does the Phones table references the Employee.
Figure 1.1
The unidirectional sample that should be discussed right now, will activate the one path of association, in that the phone entity will only reference an employee, even if a list of phone entities would reference the same employee, they are capable of. Let’s see the Phone class
package net.javabeat.eclipselink.data; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; @Entity(name="Phones") public class Phone { @Id private int phoneId; private int phoneNumber; @ManyToOne(cascade=CascadeType.ALL) @JoinColumn(name="employeeId") private Employee employee; public int getPhoneId() { return phoneId; } public void setPhoneId(int phoneId) { this.phoneId = phoneId; } public int getPhoneNumber() { return phoneNumber; } public void setPhoneNumber(int phoneNumber) { this.phoneNumber = phoneNumber; } public Employee getEmployee() { return employee; } public void setEmployee(Employee employee) { this.employee = employee; } }
The previous snippet of code covers the ManyToOne association, but let’s understand what’s happened there:
- The phone(s) entities reference an employee using the ManyToOne annotation, cause the occurrences of multiple phones with an employee is possible. Using OneToOne kind of association will not be acceptable here, even though the OneToOne annotation defines a single-valued association, but it won’t accept multiple occurrences of phones for one employee, cause the OneToOne annotation defines a single-valued association to another entity that has one-to-one multiplicity.
- The phone(s) are aware about their target employee, but the employee didn’t know anything about the phones that they are associated with. (Unidirectional association).
- ManyToOne association covering the unidirectional association of OneToMany relationship.
- No changes has been made on the Employee entity.
- The foreign key of relationship is defined in the Phone table, so the @JoinColumn is used. By that the Phone entity has owned the association.
- The cascade attribute is used to let the JPA implementation cascaded all operations into the target of the association.
- The ManyToOne has never ever be used with a conjunction of mappedBy. That’s logic, cause the entity that has ManyToOne does consider the owner of any relation that could be established between two entities that has the (OneToMany – ManyToOne) multiplicity kind of association. Refer the ManyToOne Anatomy.
Required Persistence Configuration
There is no additional fragment of lines that should be added to achieve the ManyToOne association, except that line that should define a Phone entity inside the persistence context.
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="EclipseLink-JPA-Installation" transaction-type="RESOURCE_LOCAL"> <class>net.javabeat.eclipselink.data.Employee</class> <class>net.javabeat.eclipselink.data.Address</class> <class>net.javabeat.eclipselink.data.Phone</class> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/JavaBeat"/> <property name="javax.persistence.jdbc.user" value="root"/> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> <property name="javax.persistence.jdbc.password" value="root"/> <property name="eclipselink.logging.level" value="OFF"/> </properties> </persistence-unit> </persistence>
ManyToOne Sample Application
public static void main(String [] args){ em.getTransaction().begin(); createPhone(); em.getTransaction().commit(); } public static void createPhone(){ // Create an address entity Address address = new Address(); address.setAddressId(1); address.setAddressCountry("United Kingdom"); address.setAddressCity("London"); // Create an employee entity Employee employee = new Employee(); employee.setEmployeeId(1); employee.setEmployeeName("John Smith"); // Associate the address with the employee employee.setAddress(address); // Create a Phone entity Phone phone = new Phone(); phone.setPhoneId(1); phone.setPhoneNumber("+221 4050 615"); phone.setEmployee(employee); // Persist the phone into database em.persist(phone); }
- The main program is responsible of creating a new instance of phone.
- The phone entity is associated with an employee.
- Creating of second new phone object associated with the used employee before, is acceptable.
Multiple Phone Entities
The following example shows you possibility of creating multiple phones objects that are associated with the same employee object
public static void main(String [] args){ em.getTransaction().begin(); createPhone(); em.getTransaction().commit(); } public static void createPhone(){ // Create an address entity Address address = new Address(); address.setAddressId(1); address.setAddressCountry("United Kingdom"); address.setAddressCity("London"); // Create an employee entity Employee employee = new Employee(); employee.setEmployeeId(1); employee.setEmployeeName("John Smith"); // Associate the address with the employee employee.setAddress(address); // Create a Phone entity Phone firstPhone = new Phone(); firstPhone.setPhoneId(1); firstPhone.setPhoneNumber("+221 4050 615"); firstPhone.setEmployee(employee); // Create a new phone entity Phone secondPhone = new Phone(); secondPhone.setPhoneId(2); secondPhone.setPhoneNumber("+221 4050 617"); // Use the old employee entity secondPhone.setEmployee(employee); // Persist the two phones into database em.persist(firstPhone); em.persist(secondPhone); }
@OneToMany Applies The Bidirectional Association
By using of @OneToMany, the bidirectional association for the ManyToOne has been achieved. Now, the @OneToMany will annotate a list property of type phone at the employee. OneToMany can be used with a conjunction of mappedBy. If you’ve looked at the anatomy of OneToMany, you should see the mappedBy attribute. Meanwhile, as mentioned earlier the entity that has the ManyToOne annotation does consider the owner of the relation. So if you would like to have a list of phones inside each employee that have been created, you’ve to declare a new attribute called phones within your employee entity. See the Employee entity, that has been changed to contains the phones that are used by the employee.
package net.javabeat.eclipselink.data; import java.util.List; import javax.persistence.Basic; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToMany; import javax.persistence.OneToOne; @Entity public class Employee { @Id private int employeeId; @Basic(optional=false) private String employeeName; @OneToMany(mappedBy="employee", cascade=CascadeType.ALL) private List<Phone> phones; @OneToOne(cascade=CascadeType.ALL) @JoinColumn(name="AddressId") private Address address; public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public int getEmployeeId() { return employeeId; } public void setEmployeeId(int employeeId) { this.employeeId = employeeId; } public String getEmployeeName() { return employeeName; } public void setEmployeeName(String employeeName) { this.employeeName = employeeName; } public List<Phone> getPhones() { return phones; } public void setPhones(List<Phone> phones) { this.phones = phones; } }
Employee Entity has Phone List Sample Application
public static void main(String [] args){ em.getTransaction().begin(); createEmployee(); em.getTransaction().commit(); } public static void createEmployee(){ // Create an address entity Address address = new Address(); address.setAddressId(1); address.setAddressCountry("United Kingdom"); address.setAddressCity("London"); // Create an employee entity Employee employee = new Employee(); employee.setEmployeeId(1); employee.setEmployeeName("John Smith"); // Associate the address with the employee employee.setAddress(address); // Create a Phone entity Phone firstPhone = new Phone(); firstPhone.setPhoneId(1); firstPhone.setPhoneNumber("+221 4050 615"); firstPhone.setEmployee(employee); // Create a new phone entity Phone secondPhone = new Phone(); secondPhone.setPhoneId(2); secondPhone.setPhoneNumber("+221 4050 619"); // Use the old employee entity secondPhone.setEmployee(employee); // Create a list of phone List<Phone> phones = new ArrayList<Phone>(); phones.add(firstPhone); phones.add(secondPhone); // Set the phones into your employee employee.setPhones(phones); // Persist the employee em.persist(employee); }
- The Employee entity has a list of phones. So the Employee entity capable of accessing the phones that are belong to, also every piece of phone in the employee’s phones list has a reference to the employee.
- The Persisting of employee causes a persistence of address and list of phones, that’s because of cascade.
- The Transaction manager is a mandatory concept that has never ever can be forgotten, cause the JPA requires the demarcation of the transaction to be achieved successfully.
Summary
The OneToMany and ManyToOne annotations are used together once the programmer coming into develop a bidirectional association for such that type of relation. @ManyToOne does consider the owner of the association, so you’ve noticed the @JoinColumn. Once you’re coming into OneToMany annotation, you’ve noticed using of mappedBy. That’s mean one thing; the employee is a non-owner side of association. The cascade attribute being used, is the only attribute that can help us cascaded the operations that being made on the entity. So to persist the employee and its relative entities, you should be cascaded the annotations that represents the association.