ZK Hibernate one to one annotation mapping bidirectional CRUD example using MVVM

In this post, we will see how we can implement hibernate one to one mapping bidirectional using ZK Components

In bi-directional mapping, the parent table can be retrieved by the child table and the child table can be retrieved by the parent table. Means retrieval can be done in both direction or bi-directional. In this example, we have two tables caller persona and users. We will create CRUD operation for users which also takes care of inserting record in the person tabke.

ZK Version 6
Project Name : HibernateOneToOneMap
Project Structure

image

Step 1:  ZK + Hibernate Setup
Please
follow this post to setup the Project and related jar files needed for this example

Mysql

image

CREATE  TABLE IF NOT EXISTS `sampledb`.`person` (
  `ID` BIGINT(20) NOT NULL AUTO_INCREMENT ,
  `FirstName` VARCHAR(100) NULL DEFAULT NULL ,
  `LastName` VARCHAR(100) NULL DEFAULT NULL ,
  `Email` VARCHAR(100) NULL DEFAULT NULL ,
  PRIMARY KEY (`ID`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1

CREATE  TABLE IF NOT EXISTS `sampledb`.`userlogin` (
  `ID` BIGINT(20) NOT NULL AUTO_INCREMENT ,
  `LoginID` VARCHAR(100) NULL DEFAULT NULL ,
  `Password` VARCHAR(100) NULL DEFAULT NULL ,
  `PersonID` BIGINT(20) NULL DEFAULT NULL ,
  PRIMARY KEY (`ID`) ,
  INDEX `FK_userlogin` (`PersonID` ASC) ,
  CONSTRAINT `FK_userlogin`
    FOREIGN KEY (`PersonID` )
    REFERENCES `sampledb`.`person` (`ID` ))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1

person.java

package domain;

import javax.persistence.Column;
import javax.persistence.OneToOne;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;


@Entity
@Table(name = "person")
public class person {

@Id
@GeneratedValue
private int ID;

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

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

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

@OneToOne(mappedBy = "person")
@Cascade(CascadeType.ALL)
private userlogin userlogin;


public userlogin getUserlogin() {
return userlogin;
}

public void setUserlogin(userlogin userlogin) {
this.userlogin = userlogin;
}

public int getID() {
return ID;
}

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

public String getFirstName() {
return FirstName;
}

public void setFirstName(String firstName) {
FirstName = firstName;
}

public String getLastName() {
return LastName;
}

public void setLastName(String lastName) {
LastName = lastName;
}

public String getEmail() {
return Email;
}

public void setEmail(String email) {
Email = email;
}

}

userlogin.java


package domain;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@Entity
@Table(name = "userlogin")
public class userlogin implements Serializable, Cloneable {

@Id
@GeneratedValue
private int ID;

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

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


@OneToOne(targetEntity = person.class)
@Cascade(CascadeType.ALL)
@JoinColumn(name = "personid")
private person person;


public person getPerson() {
return person;
}

public void setPerson(person person) {
this.person = person;
}

public int getID() {
return ID;
}

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

public String getLoginID() {
return LoginID;
}

public void setLoginID(String loginID) {
LoginID = loginID;
}

public String getPassword() {
return Password;
}

public void setPassword(String password) {
Password = password;
}




public Object clone() throws CloneNotSupportedException {
/*
* Employee copyObj = new Employee();
* copyObj.setDesignation(this.designation); copyObj.setName(this.name);
* return copyObj;
*/
return super.clone();
}

}

HibernateUtil.java

package HibernateUtilities;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

public class HibernateUtil {

private static SessionFactory factory;
private static ServiceRegistry serviceRegistry;

public static Configuration getInitConfiguration() {
Configuration config = new Configuration();
config.configure();
return config;
}

public static Session getSession() {
if (factory == null) {
Configuration config = HibernateUtil.getInitConfiguration();
serviceRegistry = new ServiceRegistryBuilder().applySettings(
config.getProperties()).buildServiceRegistry();
factory = config.buildSessionFactory(serviceRegistry);
}
Session hibernateSession = factory.getCurrentSession();
return hibernateSession;
}

public static Session beginTransaction() {
Session hibernateSession;
hibernateSession = HibernateUtil.getSession();
hibernateSession.beginTransaction();
return hibernateSession;
}

public static void CommitTransaction() {
HibernateUtil.getSession().getTransaction().commit();
}

public static void closeSession() {
HibernateUtil.getSession().close();
}

public static void rollbackTransaction() {
HibernateUtil.getSession().getTransaction().rollback();
}

}

 

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>

<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>

<!-- Mapping Classes -->
<mapping class="domain.person" />
<mapping class="domain.userlogin" />

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



UserCRUDVM.java


package domainVM;

import java.util.HashMap;
import java.util.Map;

import domain.person;
import domain.userlogin;

import org.zkoss.bind.BindUtils;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.bind.annotation.ExecutionArgParam;
import org.zkoss.bind.annotation.Init;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.select.Selectors;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zul.Window;

import DAO.userDAO;

public class UserCRUDVM {

private userlogin selectedItem;
private userlogin selectedItemOrg;
private boolean makeAsReadOnly;

@Wire("#win")
private Window win;

public boolean isMakeAsReadOnly() {
return makeAsReadOnly;
}

public void setMakeAsReadOnly(boolean makeAsReadOnly) {
this.makeAsReadOnly = makeAsReadOnly;
}


public userlogin getSelectedItem() {
return selectedItem;
}

public void setSelectedItem(userlogin s1) {
this.selectedItem = s1;
}

@Init
@NotifyChange("selectedItem")
public void initSetup(@ContextParam(ContextType.VIEW) Component view,
@ExecutionArgParam("selectedItem") userlogin s1,
@ExecutionArgParam("recordMode") String recordMode)
throws CloneNotSupportedException {
Selectors.wireComponents(view, this, false);


if (recordMode == "NEW") {
this.selectedItem = new userlogin();
this.selectedItemOrg = new userlogin();
this.selectedItem.setPerson(new person());
}

if (recordMode == "EDIT") {
this.selectedItemOrg = s1;
this.selectedItem = (userlogin) s1.clone();
}

if (recordMode == "READ") {
this.selectedItemOrg = s1;
this.selectedItem = (userlogin) s1.clone();
setMakeAsReadOnly(true);
win.setTitle(win.getTitle() + " (Readonly)");
}

}

@Command
public void save() {

// userlogin u1 = new userlogin();
// u1.setLoginID("sen4");
// u1.setPassword("sen4");
//
// person p1 = new person();
// p1.setEmail("senth4il@mail.com");
// p1.setFirstName("sen4thil");
// p1.setLastName("muth4iah");
// u1.setPerson(p1);
new userDAO().saveOrUpdate(this.selectedItem );
Map args = new HashMap();
args.put("newadded", this.selectedItem);
BindUtils.postGlobalCommand(null, null, "refreshList", args);
win.detach();
}
@Command
public void closeThis() {
win.detach();
}
}

userVM.java

package domainVM;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import DAO.userDAO;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.GlobalCommand;
import org.zkoss.bind.annotation.NotifyChange;
import org.zkoss.zk.ui.Executions;

import domain.userlogin;

public class userVM {

private List<userlogin> users = null;
private userlogin selectedItem;

public userlogin getSelectedItem() {
return selectedItem;
}

public void setSelectedItem(userlogin selectedItem) {
this.selectedItem = selectedItem;
}

public List<userlogin> getallUsers() {
if (users == null) {
users = new ArrayList<userlogin>();
users = new userDAO().getAllUsersFromDB();
}
return users;
}

@Command
public void addNewUser() {
final HashMap<String, Object> map = new HashMap<String, Object>();
map.put("selectedItem", null);
map.put("recordMode", "NEW");
Executions.createComponents("AddUser.zul", null, map);
}

@Command
@NotifyChange("selectedItem")
public void editThisUser() {
final HashMap<String, Object> map = new HashMap<String, Object>();
map.put("recordMode", "EDIT");
map.put("selectedItem", this.selectedItem);
Executions.createComponents("AddUser.zul", null, map);
}

@Command
public void openAsReadOnly() {
final HashMap<String, Object> map = new HashMap<String, Object>();
map.put("recordMode", "READ");
map.put("selectedItem", this.selectedItem);
Executions.createComponents("AddUser.zul", null, map);
}

@GlobalCommand
@NotifyChange("allUsers")
public void refreshList(@BindingParam("newadded") userlogin p1) {
users = null;
}
}







demo.zul

<?page title="Listitem MVVM Demo with Hibernate" contentType="text/html;charset=UTF-8"?>
<zk>

<style>

/* Start: Action Images- Edit
---------------------------------------------- */

.fimageedit { width: 25px; background-image:
url('./images/icon-edit.png'); background-repeat: no-repeat;
border: 0 none; cursor: pointer; }

/* End: Action Images - Edit
---------------------------------------------- */


/* Start: Action Images- Delete
---------------------------------------------- */

.fimageDelete { width: 25px; background-image:
url('./images/icon-trash-red.png'); background-repeat:
no-repeat; border: 0 none; cursor: pointer; }

/* End: Action Images - Delete
---------------------------------------------- */
.z-listcell.highlightcell .z-listcell-cnt,
.z-label.highlightcell { color:blue; cursor: pointer; }


</style>

<window title="Hibernate one to one Mapping bidirectional "
border="normal" apply="org.zkoss.bind.BindComposer"
viewModel="@id('myvm') @init('domainVM.userVM')">
<div>
<button label="Add User" onClick="@command('addNewUser')" />
</div>
<separator />

<listbox id="test" selectedItem="@bind(myvm.selectedItem)"
model="@load(myvm.allUsers)">
<listhead sizable="true">
<listheader label="Login ID" width="200px" />
<listheader label="Password" width="200px" />
<listheader label="First Name" width="200px" />
<listheader label="Last Name" width="285px" />
<listheader label="email" width="285px" />
<listheader label="Action" />
</listhead>
<template name="model" var="p1">
<listitem>
<listcell label="@load(p1.loginID)" />
<listcell label="@load(p1.password)" />
<listcell label="@load(p1.person.firstName)" />
<listcell label="@load(p1.person.lastName)" />
<listcell label="@load(p1.person.email)" />
<listcell>
<hbox spacing="20px">
<image sclass="fimageDelete" />
<image sclass="fimageedit"
onClick="@command('editThisUser')" />
</hbox>
</listcell>
</listitem>
</template>
</listbox>
</window>
</zk>


AddUser.zul

<zk>
<window id="win" title="User" width="520px" height="280px"
border="normal" minimizable="false" mode="modal" maximizable="false"
closable="true" action="show: slideDown;hide: slideUp"
apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('domainVM.UserCRUDVM')">
<separator />
<label value="User information" />
<separator />
<panel width="100%">
<panelchildren>
<separator />
<grid width="99.5%">
<columns>
<column label="" width="150px" />
<column label="" />
</columns>
<rows>
<row>
<hbox>
<label value="Login" />
<label value="*" />
</hbox>
<textbox name="Login ID" cols="50"
value="@bind(vm.selectedItem.loginID)" />
</row>
<row>
<hbox>
<label value="Password" />
<label value="*" />
</hbox>
<textbox name="Password" cols="50"
value="@bind(vm.selectedItem.password)" />
</row>

<row>
<hbox>
<label value="First Name" />
<label value="*" />
</hbox>
<textbox name="firstName" cols="50"
value="@bind(vm.selectedItem.person.firstName)" />
</row>
<row>
<hbox>
<label value="Last Name" />
<label value="*" />
</hbox>
<textbox name="firstName" cols="50"
value="@bind(vm.selectedItem.person.lastName)" />
</row>
<row>
<hbox>
<label value="email" />
<label value="*" />
</hbox>
<textbox name="email" cols="50"
value="@bind(vm.selectedItem.person.email)" />
</row>
</rows>
</grid>
</panelchildren>
</panel>
<separator />
<div align="center">
<button id="submit" label="Submit"
onClick="@command('save')" />
<button id="cancel" label="Cancel"
onClick="@command('closeThis')" />
</div>
</window>
</zk>



Now you can run demo.zul and add/edit the users

You can download source here