Requirement Constraints

  • Subscribe to our RSS feed.
  • Twitter
  • StumbleUpon
  • Reddit
  • Facebook
  • Digg

Friday, 3 August 2012

One to many mapping using bidirectional relationship – onetoMany as Owner

Posted on 21:49 by Unknown

First let us look the hibernate documentation on this as follows

To map a bidirectional one to many, with the one-to-many side as the owning side, you have to remove the mappedBy element and set the many to one @JoinColumn as insertable and updatable to false. This solution is not optimized and will produce some additional UPDATE statements.

http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-mapping
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/

@Entity
public class Troop {
    @OneToMany
    @JoinColumn(name="troop_fk") //we need to duplicate the physical information
    public Set<Soldier> getSoldiers() {
    ...
}

@Entity
public class Soldier {
    @ManyToOne
    @JoinColumn(name="troop_fk", insertable=false, updatable=false)
    public Troop getTroop() {
    ...
}

Now let us goto our example.

In this example, we will see one to many  as owning side i.e master is now owner. As per this example,
Department is  the owner.

image_thumb6

Step : 2

Let us set the environment. Follow this post to set up Hibernate with java in eclipse IDE.

Step : 3

Let us create all our java bean files

Department.java

package domain;


import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Table;
import javax.persistence.OneToMany;

@Entity
@Table(name = "department")
public class Department {

@Id
@GeneratedValue
@Column(name = "ID")
private int ID;

@Column(name = "DepartName")
private String departName;

/**
/* To map a bidirectional one to many, with the one-to-many side as the owning side, you have to remove the mappedBy element and
* set the many to one @JoinColumn as insertable and updatable to false. This solution is not optimized and will produce some
* additional UPDATE statements.
* Using JoinColumn makes the join-table the many side of association.
* Using JoinColumn puts an association into the many side of the one-to-many and it is that column that is used to join the two entities,
* not an extra table.
* http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-mapping
*/

/** I am the owner**/
@OneToMany(cascade={CascadeType.ALL})
@JoinColumn(name="DepartmentID", nullable = false)
List<Employees> employees;

public int getID() {
return ID;
}

public void setID(int iD) {
ID = iD;
}

public String getDepartName() {
return departName;
}

public void setDepartName(String departName) {
this.departName = departName;
}

public List<Employees> getEmployees() {
return employees;
}

public void setEmployees(List<Employees> employees) {
this.employees = employees;
}



}


Employees.java


package domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.ManyToOne;
import javax.persistence.JoinColumn;

import org.hibernate.annotations.ForeignKey;

@Entity
@Table(name = "employees")
public class Employees {

@Id
@GeneratedValue
private int ID;
@Column(name = "firstName")
private String firstName;

@Column(name = "lastName")
private String lastName;

@ManyToOne
@JoinColumn(name = "DepartmentID", insertable = false, updatable = false)
private Department department;

public int getID() {
return ID;
}

public void setID(int iD) {
ID = iD;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public Department getDepartment() {
return department;
}

public void setDepartment(Department department) {
this.department = department;
}

}

hibernate.cfg.xml


 


<?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>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/sampledb</property>
<property name="connection.username">root</property>
<property name="connection.password">123</property>

<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>

<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>

<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>

<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>



<!-- Mapping Classes -->
<mapping class="domain.Department" />
<mapping class="domain.Employees" />

</session-factory>
</hibernate-configuration>


Test Class


package test;

import java.util.ArrayList;
import java.util.List;
import org.hibernate.Session;
import domain.*;
import HibernateUtilities.*;

public class Test {

public static void main(String[] args) {

addNewMasterAndDetail();

}

public static void addNewMasterAndDetail()
{
// Now let us create Department
Department d1 = new Department();
d1.setDepartName("Accounts");

// Now let us some employees
List<Employees> empList = new ArrayList<Employees>();
Employees e1 = new Employees();

e1.setFirstName("John");
e1.setFirstName("Mike");
e1.setDepartment(d1);
empList.add(e1);

e1 = new Employees();
e1.setFirstName("Smith");
e1.setFirstName("Robert");
e1.setDepartment(d1);
empList.add(e1);

d1.setEmployees(empList);

Session session = HibernateUtil.beginTransaction();
session.save(d1);
HibernateUtil.CommitTransaction();

}

}


Now let us run our test.java and let us the look output.

Hibernate: insert into department (DepartName) values (?)
Hibernate: insert into employees (firstName, lastName, DepartmentID) values (?, ?, ?)
Hibernate: insert into employees (firstName, lastName, DepartmentID) values (?, ?, ?)
Hibernate: update employees set DepartmentID=? where ID=?
Hibernate: update employees set DepartmentID=? where ID=?


Now let us do some research and understand the concept.


In this department.java, you can see how we declare the one to many relationship






/** I am the owner**/
    @OneToMany(cascade={CascadeType.ALL})
    @JoinColumn(name="DepartmentID", nullable = false)
    List<Employees> employees;


1. Why we used nullable = false ??  Well, we will remove that as follow and run our test.java once again.


/** I am the owner**/
    @OneToMany(cascade={CascadeType.ALL})
    @JoinColumn(name="DepartmentID")
    List<Employees> employees;


Now, hibernate will throw an error as follows:
Hibernate: insert into department (DepartName) values (?)
Hibernate: insert into employees (firstName, lastName) values (?, ?)
Aug 4, 2012 11:18:14 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 1364, SQLState: HY000
Aug 4, 2012 11:18:14 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Field 'DepartmentID' doesn't have a default value
Exception in thread "main" org.hibernate.exception.GenericJDBCException: Field 'DepartmentID' doesn't have a default value
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54)


This is because we have defined as not null column in employee table for the column departmentID.
Now just for testing, let us make employee.department column as null and will remove the entire joincolumn annotation itself as follows


/** I am the owner**/
    @OneToMany(cascade={CascadeType.ALL})
     List<Employees> employees;


Now we run the test.java, you will see some different error as follows


Aug 4, 2012 11:21:55 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 1146, SQLState: 42S02
Aug 4, 2012 11:21:55 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: Table 'sampledb.department_employees' doesn't exist
Exception in thread "main" org.hibernate.exception.SQLGrammarException: Table 'sampledb.department_employees' doesn't exist


Well, this is tricky, hibernate looking for the third table to make the relationship between department and employee. In the database model, in order to make one to many relationship, either we can have the third table or we can define the foreign key in the child table that refers to master.


Rough scheme


Department (ID Primary Key, Name varchar(100)
Employee(ID Primary Key, FirstName Varchar(100)
Department_Employee(Department_ID foreign key to department, Employee_ID foreign key to Employee)


But in our example, we are using the foreign key concept without the third table for mapping between department and employee. So let us roll back all our changes and will continue from there.


Rollback in the department.java as follows


/** I am the owner**/
    @OneToMany(cascade={CascadeType.ALL})
    @JoinColumn(name="DepartmentID", nullable = false)
    List<Employees> employees;


And also, make departmentid in the employee table as not null.


And also,


What does CascadeType.ALL do?


CascadeType.PERSIST: cascades the persist (create) operation to associated entities persist() is called or if the entity is managed
CascadeType.MERGE: cascades the merge operation to associated entities if merge() is called or if the entity is managed
CascadeType.REMOVE: cascades the remove operation to associated entities if delete() is called
CascadeType.REFRESH: cascades the refresh operation to associated entities if refresh() is called
CascadeType.DETACH: cascades the detach operation to associated entities if detach() is called
CascadeType.ALL: all of the above


Now again let us run the test.java.  You can see the sql query as follows


Hibernate: insert into department (DepartName) values (?)
Hibernate: insert into employees (firstName, lastName, DepartmentID) values (?, ?, ?)
Hibernate: insert into employees (firstName, lastName, DepartmentID) values (?, ?, ?)
Hibernate: update employees set DepartmentID=? where ID=?
Hibernate: update employees set DepartmentID=? where ID=?


If you observe carefully, hibernate using the extra update statement to update the child with the parent table key. We can also optimize this by changing in the department.java as follows


/** I am the owner**/
@OneToMany(cascade={CascadeType.ALL})
@JoinColumn(name="DepartmentID", updatable = false,  nullable = false)
List<Employees> employees;


Now let us run test.java again. Now you can see the query as follows


Hibernate: insert into department (DepartName) values (?)
Hibernate: insert into employees (firstName, lastName, DepartmentID) values (?, ?, ?)
Hibernate: insert into employees (firstName, lastName, DepartmentID) values (?, ?, ?)


 


Now let us move further updating master, deleting master, update child, etc


Just in the mysql, do the following


TRUNCATE department
TRUNCATE employees


Now let us update only master. Change the test.java as follows and we will run one by one.




package test;

import java.util.ArrayList;
import java.util.List;
import org.hibernate.Session;
import domain.*;
import HibernateUtilities.*;

public class Test {
public static void main(String[] args) {
addNewMasterAndDetail();
//updateOnlyMaster();
//updateonlyDetail();
//deleteOnlyDetail();
//deleteMaster();
}

public static void addNewMasterAndDetail()
{
// Now let us create Department
Department d1 = new Department();
d1.setDepartName("Accounts");

// Now let us some employees
List<Employees> empList = new ArrayList<Employees>();
Employees e1 = new Employees();

e1.setFirstName("John");
e1.setFirstName("Mike");
e1.setDepartment(d1);
empList.add(e1);

e1 = new Employees();
e1.setFirstName("Smith");
e1.setFirstName("Robert");
e1.setDepartment(d1);
empList.add(e1);

d1.setEmployees(empList);

Session session = HibernateUtil.beginTransaction();
session.save(d1);
HibernateUtil.CommitTransaction();

}

public static void updateOnlyMaster()
{
//Now Let us update the master alone i.e Department
Session session = HibernateUtil.beginTransaction();
Department d2 = (Department) session.createQuery("from Department where id = 1").uniqueResult();
d2.setDepartName("Accounts Modified");
session.save(d2);
HibernateUtil.CommitTransaction();
}


public static void updateonlyDetail()
{
//Now Let us update the detail alone i.e employee
Session session = HibernateUtil.beginTransaction();
Department d2 = (Department) session.createQuery("from Department where id = 1").uniqueResult();
d2.getEmployees().get(0).setFirstName("changed first name");
session.save(d2);
HibernateUtil.CommitTransaction();
}

public static void deleteOnlyDetail()
{
//Now Let us update the master alone i.e Department
Session session = HibernateUtil.beginTransaction();
Department d2 = (Department) session.createQuery("from Department where id = 2").uniqueResult();
d2.getEmployees().clear();
session.saveOrUpdate(d2);
HibernateUtil.CommitTransaction();
}

public static void deleteMaster()
{
//Now Let us update the master alone i.e Department
Session session = HibernateUtil.beginTransaction();
Department d2 = (Department) session.createQuery("from Department where id = 1").uniqueResult();
session.delete(d2);
HibernateUtil.CommitTransaction();
}


}



1. Now Run the test.java and observer the sql output as follows

Hibernate: insert into department (DepartName) values (?)
Hibernate: insert into employees (firstName, lastName, DepartmentID) values (?, ?, ?)
Hibernate: insert into employees (firstName, lastName, DepartmentID) values (?, ?, ?)


2. Now in the test.java, comment the first method and uncomment the second method as follows


public static void main(String[] args) {
        //addNewMasterAndDetail();
        updateOnlyMaster();
        //updateonlyDetail();
        //deleteOnlyDetail();
        //deleteMaster();
    }


  SQL Output as follows:
Hibernate: select department0_.ID as ID0_, department0_.DepartName as DepartName0_ from department department0_ where department0_.ID=1
Hibernate: update department set DepartName=? where ID=?

3. Now in the test.java, comment all the method and uncomment updateonlyDetail and run test.java.

Hibernate: select department0_.ID as ID0_, department0_.DepartName as DepartName0_ from department department0_ where department0_.ID=1
Hibernate: select employees0_.DepartmentID as Departme4_0_1_, employees0_.ID as ID1_, employees0_.ID as ID1_0_, employees0_.DepartmentID as Departme4_1_0_, employees0_.firstName as firstName1_0_, employees0_.lastName as lastName1_0_ from employees employees0_ where employees0_.DepartmentID=?
Hibernate: update employees set firstName=?, lastName=? where ID=?


3. Now in the test.java, comment all the method and uncomment deleteOnlyDetail and run test.java. Here is the sql output

Hibernate: select department0_.ID as ID0_, department0_.DepartName as DepartName0_ from department department0_ where department0_.ID=1
Hibernate: select employees0_.DepartmentID as Departme4_0_1_, employees0_.ID as ID1_, employees0_.ID as ID1_0_, employees0_.DepartmentID as Departme4_1_0_, employees0_.firstName as firstName1_0_, employees0_.lastName as lastName1_0_ from employees employees0_ where employees0_.DepartmentID=?

Here is a problem, hibernate actually not deleting the detail. So we need to do something


orphanRemoval is an entirely ORM-specific thing. It marks "child" entity to be removed when it's no longer referenced from the "parent" entity, e.g. when you remove the child entity from the corresponding collection of the parent entity.

So let us change our department.java as follows

/** I am the owner**/
@OneToMany(cascade={CascadeType.ALL},  orphanRemoval=true)
@JoinColumn(name="DepartmentID", updatable = false,  nullable = false)
List<Employees> employees


Now again run test.java, you can see the query output as follows

Hibernate: select department0_.ID as ID0_, department0_.DepartName as DepartName0_ from department department0_ where department0_.ID=1
Hibernate: select employees0_.DepartmentID as Departme4_0_1_, employees0_.ID as ID1_, employees0_.ID as ID1_0_, employees0_.DepartmentID as Departme4_1_0_, employees0_.firstName as firstName1_0_, employees0_.lastName as lastName1_0_ from employees employees0_ where employees0_.DepartmentID=?
Hibernate: delete from employees where ID=?
Hibernate: delete from employees where ID=?


3. Finally, we will delete the master and then it will delete the detail too.
Hibernate: select department0_.ID as ID0_, department0_.DepartName as DepartName0_ from department department0_ where department0_.ID=1
Hibernate: select employees0_.DepartmentID as Departme4_0_1_, employees0_.ID as ID1_, employees0_.ID as ID1_0_, employees0_.DepartmentID as Departme4_1_0_, employees0_.firstName as firstName1_0_, employees0_.lastName as lastName1_0_ from employees employees0_ where employees0_.DepartmentID=?
Hibernate: delete from employees where ID=?
Hibernate: delete from employees where ID=?
Hibernate: delete from department where ID=?


 


That’s all.


Email ThisBlogThis!Share to XShare to Facebook
Posted in Hibernate Mapping | No comments
Newer Post Older Post Home

0 comments:

Post a Comment

Subscribe to: Post Comments (Atom)

Popular Posts

  • ZK Example for inline Editing with Add New and Delete
    I am quite impressed on this demo from ZK . But adding new record and delete existing record is missing as part of typical CRUD. So i thoug...
  • EDI 5010 Documentation 837 Professional - Loop 2010BB Payer Name
    2010BB Payer Name          In this loop, all the information will be taken from Insurance master screen. Take a look of our sample screen...
  • EDI 5010 Documentation–837 - BHT - Beginning of Hierarchical Transaction
    BHT – Beginning of Hierarchical Transaction Loop Seg ID Segment Name Format Length Ref# Req Value   BHT Beginning of Hier...
  • Hibernate Validator Example 2
    In this example, we will see some more validation constraints such as @email, @past, @length, etc. And also we will also define custom error...
  • ZK Passing Parameter between two files using MVVM–Part 1
    Overview This is the first series of articles about Passing parameter between two zul files using MVVM Design pattern .This article will fo...
  • MVVM Command annotation and Notify change example
    Here is an example, how to pass parameter on a zul through MVVM Command binding annotation. ZK URL http://books.zkoss.org/wiki/ZK%20Develo...
  • History of Present Illness
    HPI - One of the main component of Clinical History. What is an HPI ? The history of present illness (HPI) is a chronological description...
  • Patient Demographics
    Patient browse (search) is the key element for any EMR / PMS Software. In my past 15 years experience, i involved more than 5 times in desig...
  • ViewModel Class Java Annotation @Init, @NotifyChange, @Command
    In following sections we'll list all syntaxes that can be used in implementing a ViewModel and applying ZK bind annotation. The ZK binde...
  • Good Website Design Links
    Form Design Label Placement in Forms International Address Fields in Web Forms 40 Eye-Catching Registration Pages blog-comment-form-...

Categories

  • Billing Process
  • C Workbook
  • C++ Workbook
  • Eclipse Tips
  • EDI 5010
  • EMR Appointment Features
  • EMR Labs Stuff
  • EMR PMS Links
  • EMR Use cases
  • EMR Vital Sign
  • Good Website Design
  • Hibernate Criteria Queries
  • Hibernate Introduction
  • Hibernate Introduction Setup
  • Hibernate Mapping
  • Hibernate POC
  • Hibernate Validator
  • Hibernate–Java Environment setup
  • HPI
  • Java
  • Maven
  • MU Certification
  • NPI
  • PQRS
  • Practice Management System
  • Spring Security
  • Tech Links
  • Today Tech Stuff
  • zk
  • ZK Hibernate
  • ZK 5 Databinding
  • ZK Application
  • ZK Calling Another ZUL
  • ZK CheckBox
  • ZK CreateComponents
  • ZK CSS
  • ZK extended Components
  • ZK Foreach
  • ZK Forum Posts
  • ZK Framework
  • ZK Hibernate Setup
  • ZK ID Space
  • ZK Include
  • ZK Installation
  • ZK iReport
  • ZK Layout
  • ZK Listitem Pagination
  • ZK Message Box
  • ZK MVC
  • ZK MVC Combox Box
  • ZK MVC CRUD Examples
  • ZK MVC Listbox
  • ZK MVVM
  • ZK MVVM Combo
  • ZK MVVM CRUD
  • ZK MVVM ListBox
  • ZK Spring
  • ZK TextBox

Blog Archive

  • ►  2013 (105)
    • ►  December (3)
    • ►  September (7)
    • ►  August (13)
    • ►  July (1)
    • ►  June (11)
    • ►  May (3)
    • ►  April (14)
    • ►  March (19)
    • ►  February (21)
    • ►  January (13)
  • ▼  2012 (177)
    • ►  December (1)
    • ►  November (13)
    • ►  October (19)
    • ►  September (24)
    • ▼  August (26)
      • Hibernate Validator - Creating custom constraints ...
      • Hibernate Validator - Creating custom constraints...
      • Hibernate Validator Example 2
      • Hibernate Validator Examples
      • Hibernate Validator Example 1
      • ZK Examples Index Page
      • Hibernate n+1 problem
      • MVVM Command annotation and Notify change example
      • EMR Most Commonly used Vital sign
      • ZK Hibernate one to Many annotation mapping bidire...
      • EDI 5010 Documentation – 837 Professional GE Funct...
      • One to many mapping using bidirectional relationsh...
      • Sample HL7 Files
      • LAB Test Panels
      • EMR In-house Lab workflow
      • One to many mapping using bidirectional relationsh...
      • Hibernate–Java Environment setup
      • Hibernate Mapping one to Many–Some useful explanat...
      • EDI 5010 Documentation 837 Professional - Loop 233...
      • EDI 5010 Documentation 837 Professional - Loop 232...
      • EDI 5010 Documentation 837 Professional - Loop 230...
      • EDI 5010 Documentation 837 Professional - Loop 230...
      • EDI 5010 Documentation 837 Professional - Loop 230...
      • EDI 5010 Documentation 837 Professional - Loop 230...
      • EDI 5010 Documentation 837 Professional - Loop 230...
      • EDI 5010 Documentation – 837 Professional SE Trans...
    • ►  July (6)
    • ►  June (37)
    • ►  May (30)
    • ►  April (16)
    • ►  March (1)
    • ►  January (4)
  • ►  2011 (5)
    • ►  December (1)
    • ►  November (1)
    • ►  July (1)
    • ►  June (1)
    • ►  April (1)
  • ►  2010 (1)
    • ►  September (1)
Powered by Blogger.

About Me

Unknown
View my complete profile