In Java Persistence API (JPA), the Many-to-Many relationship represents a common scenario where multiple instances of one entity are associated with multiple instances of another entity. This tutorial will guide you through the process of implementing a Many-to-Many relationship using JPA.
What is a Many to Many Relationship?
In a Many-to-Many relationship, entities from both sides of the relationship can be related to multiple instances of the other side. For example, in the following association, a Customer has Many Address and an Address can, in turn, have Many Customer:
To understand the implications of the Many-to-Many relationship on entity mapping and database schema we will see a practical example using a JPA/Hibernate application.
Coding a sample application
A many-to-many mapping is expressed on both the source and target entities as a @ManyToMany
annotation on the collection attributes. For example, in the following code, the Customer Entity has an addresses attribute that has been annotated with @ManyToMany. Likewise, the Address Entity has a customers attribute that has also been annotated with @ManyToMany:
@Entity public class Customer implements Serializable { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; @NotNull private String name; @NotNull private String email; @NotNull @Column(name = "phone_number") private String phoneNumber; @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) private List<Address> addresses = new ArrayList(); // Getters/Setters omitted for brevity }
Conversely, this is the Address Entity:
@Entity public class Address implements Serializable { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; @Column private String street; @Column private String city; @ManyToMany(mappedBy = "addresses") private List<Customer> customers = new ArrayList(); }
Finally, we will add a simple Stateless Bean to insert some records and fetch a Customer with the related Addresses:
@Stateless public class ServiceBean { @PersistenceContext private EntityManager em; public String create() { Customer customer1 = new Customer(); customer1.setName("John Smith"); customer1.setPhoneNumber("328/1145678"); customer1.setEmail("[email protected]"); Customer customer2 = new Customer(); customer2.setName("Frank Smith"); customer2.setPhoneNumber("313/3454643"); customer2.setEmail("[email protected]"); Address address1 = new Address(); address1.setStreet("15th Avenue"); address1.setCity("New York"); Address address2 = new Address(); address2.setStreet("Rue de Rivoli"); address2.setCity("Paris"); List<Address> list1 = new ArrayList(); list1.add(address1); list1.add(address2); customer1.setAddresses(list1); List<Address> list2 = new ArrayList(); list2.add(address1); customer2.setAddresses(list1); em.persist(customer1); em.persist(customer2); return "Created!"; } public Customer findCustomer(Long i) { Customer c = this.em.find(Customer.class, i); System.out.println("Found Customer "+c); System.out.println("Found Addresses "+c.getAddresses()); return c; } }
To run the above example using the default H2 Datasource, you can include in your persistence.xml the following persistence unit:
<persistence-unit name="primary"> <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source> <properties> <!-- Properties for Hibernate --> <property name="hibernate.hbm2ddl.auto" value="create-drop" /> <property name="hibernate.show_sql" value="true" /> </properties> </persistence-unit>
Conclusion
In this example we have learnt how to code a many-to-many relation with Hibernate/JPA and added a simple Bean to test it.
Source code for this example: https://github.com/fmarchioni/mastertheboss/tree/master/hibernate/ManyToMany