In JPA, to express one relationship to another, for example, a tourist can have a single room in a large hotel, we will use the @OneToOne annotation. How is it in details? In this tutorial, let’s learn about annotation @OneToOne in JPA!
First, I will create a Maven project as an example:
I will use Hibernate as JPA implementation so I will add Hibernate dependency as follows:
1 2 3 4 5 |
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.11.Final</version> </dependency> |
MySQL Connector:
1 2 3 4 5 |
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.6</version> </dependency> |
Suppose, I now have two tables including a tourist and a room with the following information:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
CREATE TABLE `room` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `hotel` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `tourist` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `room_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`), FOREIGN KEY (`room_id`) REFERENCES `room` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; |
As you can see, the room table has three columns: id, name and hotel with the primary key is the id column. The tourist table has columns: id, name and room_id with the primary key is id column. In the tourist table, I have defined a foreign key from the tourist table to the room table so that a tourist will be in a room and a room can only have a tourist in it.
Entity for the above tables using the @OneToOne annotation would look like below:
Entity Tourist:
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 |
package com.huongdanjava.jpaonetoone; import javax.persistence.*; @Entity @Table public class Tourist { @Id @GeneratedValue private Integer id; @Column private String name; @OneToOne @JoinColumn(name = "room_id") private Room room; 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; } public Room getRoom() { return room; } public void setRoom(Room room) { this.room = room; } } |
Entity Room:
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 51 52 53 |
package com.huongdanjava.jpaonetoone; import javax.persistence.*; @Table @Entity public class Room { @Id @GeneratedValue private Integer id; @Column private String name; @Column private String hotel; @OneToOne(mappedBy = "room") private Tourist tourist; 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; } public String getHotel() { return hotel; } public void setHotel(String hotel) { this.hotel = hotel; } public Tourist getTourist() { return tourist; } public void setTourist(Tourist tourist) { this.tourist = tourist; } } |
Because the tourist table has a column room_id which is a foreign key to the room table then in the Tourist entity, we will declare the @OneToOne annotation along with another annotation @JoinColumn to represent this relationship.
To show the opposite relationship, a room with only one tourist, I also used the @OneToOne annotation in the Room entity with the mappedBy property as room. The room attribute here is the variable name in the Tourist entity declared with the @OneToOne annotation.
OK, so we’ve finished declaring the @OneToOne annotation to show the relationship between a tourist and a room. Now let’s take an example to see how it works.
I will add the configuration file for JPA, persistence.xml, located in the /src/main/resources/META-INF directory with the following contents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<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.jpaonetoone.Room</class> <class>com.huongdanjava.jpaonetoone.Tourist</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 in the database, we have following data:
then when running the following example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
package com.huongdanjava.jpaonetoone; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; public class Application { public static void main(String[] args) { EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaexample"); EntityManager em = emf.createEntityManager(); EntityTransaction transaction = em.getTransaction(); Tourist tourist = em.find(Tourist.class, 1); System.out.println("Tourist name: " + tourist.getName() + ", room: " + tourist.getRoom().getName()); em.close(); emf.close(); } } |
the result will be: