One-To-One Mapping: One-To-One
mapping is almost same as Many-To-One mapping except that only one
instance of source entity can refer to one target entity instance. In
other words a target entity instance is shared among not more than one
source entity instance.
A
realistic example of a One-To-One mapping is the relation between a
Country and its Capital that each country has only one capital. The
following figure clearly implies the One-To-One relationship between
Country and Capital.
Here, Country is as the source in the relationship and Capital as the target. And, the arrow points only in one direction from Country to Capital which means the relationship is unidirectional. We can discuss about bidirectional One-To-One mapping later. Now let us see the step by step procedure for One-To-One mapping with this example by creating a simple java project in Eclipse.
1. Create a new Java Project
In Eclipse, Create a new Java Project 'Hiberate_App'.
2. Updating Build Path
In order to use Hibernate in our project we have to update Java Build Path as shown in screenshot:
- Right click on project and select properties.
- Select Java Build Path(1) and then Libraries(2).
- Click on Add External Jars(3) and select all required jar files to run a project using Hibernate and click Ok(4). We have updated the build path for our project to use Hibernate.
3. Creating Model Classes
In project explorer, right click on src folder and create a package with name javakart in which we will create all our .java files of our project.
Create two classes Country.java and Capital.java inside javakart package as shown below:
Country.java
Capital.java
4. Create HibernateUtil.java and Main.java for accessing data to & from database
HibernateUtil.java
Main.java
Inside src folder, create a hibernate.cfg.xml file and update it as shown below:
Here, Country is as the source in the relationship and Capital as the target. And, the arrow points only in one direction from Country to Capital which means the relationship is unidirectional. We can discuss about bidirectional One-To-One mapping later. Now let us see the step by step procedure for One-To-One mapping with this example by creating a simple java project in Eclipse.
Here, in this example we will use PostgreSQL database.
1. Create a new Java Project
In Eclipse, Create a new Java Project 'Hiberate_App'.
2. Updating Build Path
In order to use Hibernate in our project we have to update Java Build Path as shown in screenshot:
- Right click on project and select properties.
- Select Java Build Path(1) and then Libraries(2).
- Click on Add External Jars(3) and select all required jar files to run a project using Hibernate and click Ok(4). We have updated the build path for our project to use Hibernate.
3. Creating Model Classes
In project explorer, right click on src folder and create a package with name javakart in which we will create all our .java files of our project.
Create two classes Country.java and Capital.java inside javakart package as shown below:
Country.java
package javakart; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.JoinColumn; import javax.persistence.Table; @Entity @Table(name="COUNTRY") public class Country{ @Id @Column(name="country_id") private Integer countryId; @Column(name="name") private String name; @OneToOne @JoinColumn(name="cap_id") private Capital capital // Getters and Setters public Integer getCountryId() { return countryId; } public void setCountryId(Integer countryId) { this.countryId = countryId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Capital getCapital() { return capital; } public void setCapital(Capital capital) { this.capital = capital; } }
In Country.java, define One-To-One mapping by using @OneToOne annotation on the capital attribute.
And, @JoinColumn is used to specify the name of the foreign key column
that refers to a key in another table. Here, we are giving foreign key
column name as 'cap_id' by using @JoinColumn(name="cap_id"). If we didn't specify @JoinColumn
then a default name is formed from a combination of source & target
entities which is 'name of the relationship attribute in source entity'
plus 'underscore' plus 'name of the primary key column of target
entity'. Thus, the default name formed to foreign key column is
'capital_capital_id'. But, in database if this is not the actual
column name which already exists then @JoinColumn annotation must be
defined to override the default. In our example we override the default
join column name to be cap_id.
package javakart; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="CAPITAL") public class Capital{ @Id @Column(name="capital_id") private Integer capitalId; @Column(name="name") private String name; // Getters and Setters public Integer getCapitalId() { return capitalId; } public void setCapitalId(Integer capitalId) { this.capitalId = capitalId; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
HibernateUtil.java
package javakart; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class HibernateUtil { private static final SessionFactory sf = buildSessionFactory(); @SuppressWarnings("deprecation") private static SessionFactory buildSessionFactory() { try { return new Configuration().configure().buildSessionFactory(); } catch (Throwable ex) { System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static Session openSession() { return sf.openSession(); } }
Main.java
package javakart; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; public class Main{ public static void main(String[] args){ // Add Country Details Capital cap1 = new Capital(); cap1.setCapitalId(1); cap1.setName("New Delhi"); Capital cap2 = new Capital(); cap2.setCapitalId(2); cap2.setName("Jakarta"); // Add Countries Country country1 = new Country(); country1.setCountryId(1); country1.setName("India"); country1.setCapital(cap1); Country country2 = new Country(); country2.setCountryId(2); country2.setName("Indonesia"); country2.setCapital(cap2); try{ Session s = HibernateUtil.openSession(); Transaction tx = s.beginTransaction(); s.save(cap1); s.save(cap2); s.save(country1); s.save(country2); tx.commit(); s.flush(); s.close(); }catch(Exception ex){ System.out.println("Error while adding: "+ex.getMessage()); } //---- End ---- // Reading Country Details try{ Session s = HibernateUtil.openSession(); s.beginTransaction(); Query query = s.createQuery("from Country"); List5. Configure Hibernate Configuration Filelist = query.list(); System.out.println("Country \t Capital"); for(Country country:list){ System.out.print(country.getName()); System.out.print("\t"); System.out.println(country.getCapital().getName()); } }catch(Exception ex){ System.out.println("Error while reading: "+ex.getMessage()); } // ---- End ---- } }
Inside src folder, create a hibernate.cfg.xml file and update it as shown below:
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration> <session-factory> <property name="connection.driver_class">org.postgresql.Driver</property> <property name="connection.url">jdbc:postgresql://localhost/ Hibernate_Practice</property> <property name="connection.username">postgres</property> <property name="connection.password">mypassword</property> <property name="connection.pool_size">10</property> <property name="dialect">org.hibernate.dialect.PostgreSQLDialect</property> <property name="current_session_context_class">thread</property> <property name="cache.provider_class">org.hibernate.cache.internal .NoCacheProvider</property> <property name="show_sql">true</property> <property name="hbm2ddl.auto">update</property> <mapping class="javakart.Country"/> <mapping class="javakart.Capital"/> </session-factory> </hibernate-configuration>
6. Finally, our project structure will looks as shown in screenshot:
7. Try to run Main.java. In console we will find the output as:
Country Capital
John New Delhi
Indonesia Jakarta
7. Try to run Main.java. In console we will find the output as:
Hibernate: insert into CAPITAL (name, capital_id) values (?, ?) Hibernate: insert into CAPITAL (name, capital_id) values (?, ?) Hibernate: insert into COUNTRY (capital_capital_id, name, population, country_id) values (?, ?, ?, ?) Hibernate: insert into COUNTRY (capital_capital_id, name, population, country_id) values (?, ?, ?, ?)
Hibernate: select country0_.country_id as country_1_1_, country0_.capital_capital_id as capital_4_1_, country0_.name as name2_1_, country0_.population as populati3_1_ from COUNTRY country0_ Hibernate: select capital0_.capital_id as capital_1_0_0_, capital0_.name as name2_0_0_ from CAPITAL capital0_ where capital0_.capital_id=? Hibernate: select capital0_.capital_id as capital_1_0_0_, capital0_.name as name2_0_0_ from CAPITAL capital0_ where capital0_.capital_id=?
Country Capital
John New Delhi
Indonesia Jakarta