One to One Primary Key Foreign key Mapping


Requirements

  • Jdk 1.7
  • IDE (I am using Eclipse Kepler IDE)
  • Database (I am using mysql)

Download One to One PK FK Demo with jars
Download One to One PK FK Demo without jars

In one to one primary key and foreign key mapping, the relation of parent and child table depends on a column. There is one extra column required for mapping both tables. The below image is the example of pk-fk (Primary key and Foreign key) mapping. In this scenario, emp table has two columns id and name, column id is a primary key (pk). Second table emp_details has three columns id as a primary key (pk), emp_id as a foreign key (fk) and address, emp_details.emp_id is foreign key (fk) of emp.id (pk).

one-to-one-primary-key-foreign-key-jpa-hibernate-table


Step-1:- Emp.java

Emp is an entity class, which have two properties id and name.
@Entity: This class is treated as entity class. If it is not declared then throws java.lang.IllegalArgumentException: Unknown entity. It contains one parameter.
Ex: @Entity(name="test"), if @Table is not defined, then it creates a table with name in @Entity(name="emp1") otherwise creates a table name of class as emp. The name of entity is by default class name. This name can be use in HQL queries like table name in normal SQL queries.
@Table is used to create table with given name.
@Id This property is treated as primary key.
@SequenceGenerator is used to create sequence in database.
@GeneratedValue is used hold the reference of sequence.
Ex:- @SequenceGenerator(name = "emp_gen", ...) --> @GeneratedValue(generator = "emp_gen")
@Column(name="something") This annotation used on property level. If we don't declare column annotation, then jpa is treated by default column name as property name.

@OneToOne indicates one to one mapping. mappedBy = "emp1" must match with emp1 property of EmpDetails.
package com.groupofknowledge;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "emp")
public class Emp {
    @Id
    @SequenceGenerator(name = "emp_gen", sequenceName = "emp_seq", allocationSize = 1,
        initialValue = 101, schema = "gok")
    @GeneratedValue(generator = "emp_gen")
    private Integer id;
    private String name;

    @OneToOne(mappedBy = "emp1")//101;
        //This(mappedBy = "emp1") must match with the emp1 (property) of EmpDetails class

    private EmpDetails epmDetails;

    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 EmpDetails getEpmDetails() {
        return epmDetails;
    }
    public void setEpmDetails(EmpDetails epmDetails) {
        this.epmDetails = epmDetails;
    }
}

Step-2:- EmpDetails.java

EmpDetails is an entity class, which have two properties id, address and emp1.
@Entity: This class is treated as entity class. If it is not declared then throws java.lang.IllegalArgumentException: Unknown entity. It contains one parameter
Ex: @Entity(name="test"), if @Table is not defined, then it creates a table with name in @Entity(name="emp1") otherwise creates a table name of class as emp. The name of entity is by default class name. This name can be use in HQL queries like table name in normal SQL queries.
@Table is used to create table with given name. It contains name = "emp_details", it means, it will create a table with name of "emp_details" which contains three columns id, address and emp_id.
@Id This property is treated as primary key.
@SequenceGenerator is used to create sequence in database.
@GeneratedValue is used hold the reference of sequence.
Ex:- @SequenceGenerator(name = "emp_details_gen", ...) --> @GeneratedValue(generator = "emp_details_gen")

@OneToOne indicates one to one mapping. mappedBy = "emp1" must match with emp1 property of EmpDetails.
@JoinColumn(name = "emp_id") This is the foreign key column name, which joins both table emp and emp_details
package com.groupofknowledge;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity
@Table(name = "emp_details")
public class EmpDetails {
    @Id
    @SequenceGenerator(name = "emp_details_gen", sequenceName = "emp_details",
        schema = "gok", allocationSize = 1, initialValue = 1)
    @GeneratedValue(generator = "emp_details_gen")
    private Integer id;
    private String address;

    @OneToOne // It means this is the one-to-one mapping
    @JoinColumn(name = "emp_id") // emp_id (fk) in emp_details table.
    private Emp emp1;
        // 101; This property(emp1) is must match with @OneToOne(mappedBy = "emp1") in Emp class

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public Emp getEmp1() {
        return emp1;
    }
    public void setEmp1(Emp emp1) {
        this.emp1 = emp1;
    }
}

Step-3:- persistence.xml


Description:- persistence.xml file contains information of database. The specification of each tag is explained below...
<persistence-unit name="demo"></persistence-unit> tag has name="demo", which should match with javax.persistence.Persistence.createEntityManagerFactory("demo") in Main.java file.
<class>com.groupofknowledge.Emp</class> tag represents entity class.
In <property name="hibernate.show_sql" value="true"/> tag has a hibernate.show_sql property key, which contains boolean value. If value="true", it means query will be visible in console otherwise it will not be visible in console.
In <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> tag has a javax.persistence.jdbc.driver property key which indicates database driver details.
Example: The drivers are given as below for different database.
  • com.mysql.jdbc.Driver (MySql)
  • org.postgresql.Driver (PostgreSql)
  • oracle.jdbc.driver.OracleDriver (Oracle)
  • com.microsoft.sqlserver.jdbc.SQLServerDriver (SQL Server)
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test"/> has a javax.persistence.jdbc.url property key which indicates information of database connection.
The description of jdbc:mysql://localhost:3306/test is given as below...
  • localhost for local database, give IP address for remote database
  • 3306 database port
  • test database schema
Example: The different connection url's are given as below for different database.
  • jdbc:mysql://localhost:3306/test (MySql)
  • jdbc:postgresql://localhost:5432/test (PostgreSql)
  • jdbc:oracle:thin:@localhost:1521:xe (Oracle)
  • jdbc:sqlserver://MYPC\\SQLEXPRESS;databaseName=test (SQL Server)
In <property name="javax.persistence.jdbc.user" value="root"/> tag indicates the database user name.
In <property name="javax.persistence.jdbc.password" value="root" /> tag indicates the database password.
In <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> tag has a hibernate.dialect property used to generate query according to database
Example: The different dialect are given as below for different database.
  • org.hibernate.dialect.MySQLDialec (MySql)
  • org.hibernate.dialect.PostgreSQLDialect (PostgreSql)
  • org.hibernate.dialect.Oracle10gDialect (Oracle)
  • org.hibernate.dialect.SQLServerDialect (SQL Server)
In <property name="hibernate.hbm2ddl.auto" value="update"/> tag has a hibernate.hbm2ddl.auto property can contains any one value among create/update/validate/create-drop.
  • create It drops all tables and create new tables when EntityManagerFactory is initialized.
  • update It does not drop any table, it only updates the table schema.
  • validate It validates that the schema matches, make no changes to the schema of the database.
  • create-drop It drops all tables and create new tables when EntityManagerFactory is initialized. As well as it drops all tables when EntityManagerFactory is closed.
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="demo">
        <class>com.groupofknowledge.Emp</class>
        <class>com.groupofknowledge.EmpDetails</class>
        <class>com.groupofknowledge.Country</class>
        <class>com.groupofknowledge.State</class>
        <class>com.groupofknowledge.Teacher</class>
        <class>com.groupofknowledge.Student</class>
        <properties>
            <property name="hibernate.show_sql" value="true"/>
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test"/>
            <property name="javax.persistence.jdbc.user" value="root"/>
            <property name="javax.persistence.jdbc.password" value="root" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
        </properties>
    </persistence-unit>
</persistence>

Step-5:- Main.java

Run this program, then JPA will create two tables emp and emp_details. Table (emp) contains two columns id and name. Table emp_details contains three columns id, address and emp_id. It also creates two sequences emp_seq and emp_details.
Insert one row into table emp with id 1 and name Ravindra.
package com.groupofknowledge;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("demo");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        Emp e = new Emp();
        e.setName("Ravindra");
        EmpDetails ed = new EmpDetails();
        ed.setAddress("Delhi");
        ed.setEmp1(e);
        em.persist(e);
        em.persist(ed);
        em.getTransaction().commit();
    }
}

Result...


emp (Table)

id(pk) name
101 Ravindra

emp_details (Table)

id(pk) address emp_id(fk)
1 Delhi 101
Download One to One PK FK Demo with jars
Download One to One PK FK Demo without jars