Suppose, you are working on a project where the database has two tables, such as student and clazz, structured like below:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
CREATE TABLE `clazz` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `student` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `clazz_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`), FOREIGN KEY (`clazz_id`) REFERENCES `clazz` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
As you can see, the clazz table has columns id and name with the primary key id. Student table has columns id, name and clazz_id with primary key id. In this student table, we have also defined a foreign key from it to the clazz table, meaning that a class can have more than one student, and many students can be classed. In JPA, to express the relationship of many students with the same class, we will use the @ManyToOne annotation, and to express a class relationship with many students, we will use the @OneToMany annotation.
We have learned about annotation @ManyToOne in the previous tutorial. This tutorial I will be with you to learn about annotation @OneToMany.
First, I will create a Maven project to illustrate for the above example:
I will add Hibernate dependency to use JPA as follows:
1 2 3 4 5 |
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.5.Final</version> </dependency> |
In this example, I am working with MySQL so I will also add the MySQL Driver dependency as follows:
1 2 3 4 5 |
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.5</version> </dependency> |
Next, I will create the Clazz and Student entities to display their information.
The content of the Clazz entity is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
package com.huongdanjava.jpaonetomany; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table public class Clazz { @Id @GeneratedValue private Integer id; @Column private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } |
and entity Student:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
package com.huongdanjava.jpaonetomany; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table public class Student { @Id @GeneratedValue private Integer id; @Column private String name; @ManyToOne @JoinColumn(name = "clazz_id") private Clazz clazz; public Clazz getClazz() { return clazz; } public void setClazz(Clazz clazz) { this.clazz = clazz; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } |
Now, we will use the @OneToMany annotation to show the relationship of the clazz table to the student table in JPA.
Because, this is a one-to-many relationship seen from the Clazz object so I’ll put the @OneToMany annotation in the Clazz object as follows:
1 2 3 4 5 6 7 8 9 10 |
@OneToMany(mappedBy = "clazz") private Collection<Student> students; public Collection<Student> getStudents() { return students; } public void setStudents(Collection<Student> students) { this.students = students; } |
As you can see, in this annotation, I have declared an attribute mappedBy with a value is clazz. The “clazz” value here is the variable name defined with the @ManyToOne annotation in the Student entity.
Here, we have completed using the @OneToMany annotation to define the Clazz entity. I will try to see how it works.
I will add a configuration file, persistence.xml:
with the following content:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<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_2_1.xsd"> <persistence-unit name="jpaexample" transaction-type="RESOURCE_LOCAL"> <class>com.huongdanjava.jpaonetomany.Clazz</class> <class>com.huongdanjava.jpaonetomany.Student</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpaexample" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="123456" /> <property name="hibernate.format_sql" value="true" /> <property name="hibernate.use_sql_comments" value="true" /> </properties> </persistence-unit> </persistence> |
Suppose, now in the database, I have the following data:
With this code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
package com.huongdanjava.jpaonetomany; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; public class Example { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaexample"); EntityManager em = emf.createEntityManager(); EntityTransaction transaction = em.getTransaction(); Clazz clazz = em.find(Clazz.class, 1); System.out.println("Number of students: " + clazz.getStudents().size()); em.close(); emf.close(); } } |
The results will look like below: