One to One Same Primary Key Mapping


Requirements

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

Download JPA One to One Same PK Demo with jars
Download JPA One to One Same PK Demo without jars

In one to one same primary key mapping, the relation of parent and child table only on a single column. There is no extra column required for mapping both tables. In one to one primary key and foreign key mapping, one extra column required emp_id (in previous chapter), but in this example we are not required any extra column.
The below image is the example of same 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 also two columns id as a foreign key (fk) and address, emp_details.id is foreign key (fk) of emp.id (pk).

one-to-one-same-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.

@GenericGenerator is used to insert id from emp table to emp_details table. emp1 is the property of EmpDetails class.
@GeneratedValue is used hold the reference of GenericGenerator.
Ex:- @GenericGenerator(name = "gen", ...) --> @GeneratedValue(generator = "gen")
@OneToOne Indicates both class have one to one mapping.
@PrimaryKeyJoinColumn This annotation indicates, id of this (emp_details) table is the id of emp table.
package com.groupofknowledge;

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

import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

@Entity
@Table(name = "emp_details")
public class EmpDetails {
    @Id
    @GenericGenerator(name = "gen", strategy = "foreign",
        parameters = @Parameter(name = "property", value = "emp1"))     // 101; emp1 is the property of EmpDetails
    @GeneratedValue(generator = "gen")
    private Integer id;
    private String address;

    @OneToOne
    @PrimaryKeyJoinColumn
    private Emp emp1; // 101;

    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

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
1 Ravindra
2 Suman
3 Sahil

emp_details (Table)

id(fk) address
1 UP
3 Delhi
Download JPA One to One Same PK Demo with jars
Download JPA One to One Same PK Demo without jars