In this post under Hibernate, I will explain how to create a bidirectional one to one association between objects using a mapping file with an example.
For our example, we will create the below two tables.
Data Definition Language
CREATE TABLE `ticket2` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`number` VARCHAR(50) NOT NULL,
`description` VARCHAR(100) NOT NULL,
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
ROW_FORMAT=DYNAMIC
AUTO_INCREMENT=6
;
CREATE TABLE `person2` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`description` VARCHAR(100) NOT NULL,
`ticket_id` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`),
INDEX `FK_person_ticket` (`ticket_id`),
CONSTRAINT `person2_ibfk_1` FOREIGN KEY (`ticket_id`) REFERENCES `ticket2` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
ROW_FORMAT=DYNAMIC
AUTO_INCREMENT=7
;
According to above sql code, I have created two tables “ticket2” and “person2”. In Object Oriented world, there will be one to one association between “ticket2” and “person2”. In other words one “person2” instance will have one instance of “ticket2”. So to create a one to one association in RDBMS, I have added a foreign key “ticket_id” column in “person2” table. This foreign key will refer to primary column in “ticket2” table.
Next we will create java classes for the above tables
Person2
public class Person2 {
private int id;
private String name;
private String description;
private Ticket2 ticket;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Ticket2 getTicket() {
return ticket;
}
public void setTicket(Ticket2 ticket) {
this.ticket = ticket;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(id).append(":");
sb.append(name).append(":");
sb.append(description).append(":");
sb.append(getTicket());
return sb.toString();
}
}
Ticket2
public class Ticket2 {
private int id;
private String number;
private String description;
private Person2 person;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Person2 getPerson() {
return person;
}
public void setPerson(Person2 person) {
this.person = person;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(id).append(":");
sb.append(number).append(":");
sb.append(description);
return sb.toString();
}
}
Since we are creating an bidirectional one to one association meaning the navigation will be from both sides. In the “Person2” class code, we have added “ticket” property of type “Ticket2” and in “Ticket2” class we have added “person” property of type “Person2”.
Next we add hbm.xml file for the above java classes
Person2.hbm.xml
1 <?xml version="1.0"?>
2 <!DOCTYPE hibernate-mapping PUBLIC
3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
5 <hibernate-mapping>
6 <class name="Person2" table="Person2">
7 <id type="int" name="id" column="id">
8 <generator class="native"/>
9 </id>
10 <property name="name" column="name" type="string"/>
11 <property name="description" column="description" type="string"/>
12 <many-to-one name="ticket" class="Ticket2" column="ticket_id" unique="true"/>
13 </class>
14 </hibernate-mapping>
In the above xml file at line 12, I have added many-to-one element with name as “ticket”, class as “Ticket2”, column attribute value equal to foreign key column name in the “person2” table, and unique attribute equals to true.
Ticket2.hbm.xml
1 <?xml version="1.0"?>
2 <!DOCTYPE hibernate-mapping PUBLIC
3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
4 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
5 <hibernate-mapping>
6 <class name="Ticket2" table="Ticket2">
7 <id type="int" name="id" column="id">
8 <generator class="native"/>
9 </id>
10 <property name="number" column="number" type="string"/>
11 <property name="description" column="description" type="string"/>
12 <one-to-one name="person" class="Person2" property-ref="ticket"/>
13 </class>
14 </hibernate-mapping>
In the above xml file at line 12, I have added one-to-one element with name as “person” (equal to property name in corresponding java class), class as “Person2”, and property-ref attribute value equal to property name in Person2 class.
Below is hibernate configuration file for your reference
hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/examples</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- <property name="hibernate.hbm2ddl.auto">create</property> -->
<property name="hibernate.show_sql">true</property>
<mapping resource="Person2.hbm.xml"/>
<mapping resource="Ticket2.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Below is the main code
Main Code
1 import org.hibernate.Session;
2 import org.hibernate.SessionFactory;
3
4 public class HibernateDemo13 {
5 public static void main(String[] args) {
6 SessionFactory sessionFactory = HibernateUtil.createSessionFactory();
7
8 Person2 person = new Person2();
9 person.setName("Sumanth");
10 person.setDescription("description");
11
12 Ticket2 ticket = new Ticket2();
13 ticket.setNumber("Ticket1");
14 ticket.setDescription("description");
15
16 person.setTicket(ticket);
17 ticket.setPerson(person);
18
19 Session session = sessionFactory.openSession();
20 session.beginTransaction();
21 int id = (Integer)session.save(ticket);
22 session.save(person);
23 session.getTransaction().commit();
24 session.close();
25
26 ticket = null;
27
28 session = sessionFactory.openSession();
29 ticket = session.load(Ticket2.class, id);
30 System.out.println(ticket.getPerson());
31 session.close();
32 HibernateUtil.shutdown();
33 }
34}
In the main code, at line 8 we create a new instance of Person2.
At line 12, we create a new instance of Ticket2.
At line 16, we set the ticket property of person instance by calling “setTicket” method.
At line 17, we set the person property of ticket instance by calling “setPerson” method.
At line 21, we save the ticket instance, then the person instance at line 22.