JPA One to One Bi Directional Mapping using MySQL and Hibernate

In the last post we saw how to define OnetoOne mapping using JPA but it was unidirectional, which means when we load Employee we can see EmployeeAddress but vise-versa is not true.

Today we will update our mapping so that if we fetch EmployeeAddress we can obtain related Employee.

Our Employee.java will remain as it is, but we will introduce a concept of mappedBy attribute as part of @OneToOne in our EmployeeAddress.java.

Employee.java

/**
 * 
 */
package com.mumz.jpa.mapping.onetoone;

import java.io.Serializable;

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

/**
 * The Class Employee.
 * 
 * @author prabhat.jha
 */
@Entity
@Table(name = "")
public class Employee implements Serializable {
	
	/** The Constant serialVersionUID. */
	private static final long	serialVersionUID	= 578658067302993111L;

	/** The id. */
	private Long				id					= null;

	/** The name. */
	private String				name				= null;

	/** The is active. */
	private String				isActive			= null;

	/** The address. */
	private EmployeeAddress		address				= null;

	/**
	 * Gets the id.
	 * 
	 * @return the id
	 */
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "EMPLOYEE_ID")
	public Long getId() {
		return id;
	}

	/**
	 * Sets the id.
	 * 
	 * @param id
	 *            the id to set
	 */
	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * Gets the name.
	 * 
	 * @return the name
	 */
	@Column(name="EMPLOYEE_NAME")
	public String getName() {
		return name;
	}

	/**
	 * Sets the name.
	 * 
	 * @param name
	 *            the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Gets the checks if is active.
	 * 
	 * @return the isActive
	 */
	@Column(name="IS_ACTIVE")
	public String getIsActive() {
		return isActive;
	}

	/**
	 * Sets the checks if is active.
	 * 
	 * @param isActive
	 *            the isActive to set
	 */
	public void setIsActive(String isActive) {
		this.isActive = isActive;
	}

	/**
	 * Gets the address.
	 * 
	 * @return the address
	 */
	@OneToOne(cascade=CascadeType.ALL)
	@JoinColumn(name="EMPLOYEE_ADDRESS_ID")
	public EmployeeAddress getAddress() {
		return address;
	}

	/**
	 * Sets the address.
	 * 
	 * @param address
	 *            the address to set
	 */
	public void setAddress(EmployeeAddress address) {
		this.address = address;
	}

	/**
	 * (non-Javadoc).
	 * 
	 * @return the int
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((address == null) ? 0 : address.hashCode());
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result + ((isActive == null) ? 0 : isActive.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	/**
	 * (non-Javadoc).
	 * 
	 * @param obj
	 *            the obj
	 * @return true, if successful
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (!(obj instanceof Employee)) {
			return false;
		}
		Employee other = (Employee) obj;
		if (address == null) {
			if (other.address != null) {
				return false;
			}
		} else if (!address.equals(other.address)) {
			return false;
		}
		if (id == null) {
			if (other.id != null) {
				return false;
			}
		} else if (!id.equals(other.id)) {
			return false;
		}
		if (isActive == null) {
			if (other.isActive != null) {
				return false;
			}
		} else if (!isActive.equals(other.isActive)) {
			return false;
		}
		if (name == null) {
			if (other.name != null) {
				return false;
			}
		} else if (!name.equals(other.name)) {
			return false;
		}
		return true;
	}

	/**
	 * (non-Javadoc).
	 * 
	 * @return the string
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return String.format("Employee [id=%s, name=%s, isActive=%s, address=%s]", id, name, isActive, address);
	}
}

EmployeeAddress.java

package com.mumz.jpa.mapping.onetoone;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

/**
 * The Class EmployeeAddress.
 * @author prabhat.jha
 */
@Entity
@Table(name = "EMPLOYEE_ADDRESS")
public class EmployeeAddress implements Serializable {
	
	/** The Constant serialVersionUID. */
	private static final long	serialVersionUID	= -3901477366664399455L;

	/** The id. */
	private Long				id					= null;

	/** The state. */
	private String				state				= null;

	/** The city. */
	private String				city				= null;

	/** The employee. */
	private Employee			employee			= null;

	/**
	 * Gets the id.
	 * 
	 * @return the id
	 */
	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "EMPLOYEE_ADDRESS_ID")
	public Long getId() {
		return id;
	}

	/**
	 * Sets the id.
	 * 
	 * @param id
	 *            the id to set
	 */
	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * Gets the state.
	 * 
	 * @return the state
	 */
	@Column(name = "EMPLOYEE_ADDRESS_STATE")
	public String getState() {
		return state;
	}

	/**
	 * Sets the state.
	 * 
	 * @param state
	 *            the state to set
	 */
	public void setState(String state) {
		this.state = state;
	}

	/**
	 * Gets the city.
	 * 
	 * @return the city
	 */
	@Column(name = "EMPLOYEE_ADDRESS_CITY")
	public String getCity() {
		return city;
	}

	/**
	 * Sets the city.
	 * 
	 * @param city
	 *            the city to set
	 */
	public void setCity(String city) {
		this.city = city;
	}

	/**
	 * Gets the employee.
	 * 
	 * @return the employee
	 */
	@OneToOne(mappedBy="address")
	public Employee getEmployee() {
		return employee;
	}

	/**
	 * Sets the employee.
	 * 
	 * @param employee
	 *            the employee to set
	 */
	public void setEmployee(Employee employee) {
		this.employee = employee;
	}

	/**
	 * (non-Javadoc).
	 * 
	 * @return the int
	 * @see java.lang.Object#hashCode()
	 */
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((city == null) ? 0 : city.hashCode());
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result + ((getState() == null) ? 0 : getState().hashCode());
		return result;
	}

	/**
	 * (non-Javadoc).
	 * 
	 * @param obj
	 *            the obj
	 * @return true, if successful
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (!(obj instanceof EmployeeAddress)) {
			return false;
		}
		EmployeeAddress other = (EmployeeAddress) obj;
		if (city == null) {
			if (other.city != null) {
				return false;
			}
		} else if (!city.equals(other.city)) {
			return false;
		}
		if (id == null) {
			if (other.id != null) {
				return false;
			}
		} else if (!id.equals(other.id)) {
			return false;
		}
		if (getState() == null) {
			if (other.getState() != null) {
				return false;
			}
		} else if (!getState().equals(other.getState())) {
			return false;
		}
		return true;
	}

	/**
	 * (non-Javadoc).
	 * 
	 * @return the string
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return String.format("EmployeeAddress [id=%s, state=%s, city=%s]", id, getState(), city);
	}
}

To test our code we will use OneToOneUniDirectionalMainApp.java.

OneToOneUniDirectionalMainApp.java

package com.mumz.jpa.mapping.onetoone;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;

import com.mumz.jpa.JPAConnectionFactory;

public class OneToOneUniDirectionalMainApp {

	public static void main(String[] args) {
		EntityManager entityManager = JPAConnectionFactory.getEntityManager("jpaPersistenceUnit");

		Employee employee = new Employee();
		employee.setIsActive("True");
		employee.setName("Test");

		EmployeeAddress employeeAddress = new EmployeeAddress();
		employeeAddress.setCity("XYZ");
		employeeAddress.setState("ABC");
		employee.setAddress(employeeAddress);

		EntityTransaction transaction = entityManager.getTransaction();
		try {
			transaction.begin();
			entityManager.persist(employee);
			transaction.commit();
			entityManager.clear();
			employee = entityManager.find(Employee.class, new Long(1));
			employeeAddress = entityManager.find(EmployeeAddress.class, new Long(1));
			System.out.println("Fetched Employee : " + employee);
			System.out.println("Employee Inside Employee Address : " + employeeAddress.getEmployee());
		} catch (Exception e) {
			e.printStackTrace();
			transaction.rollback();
		} finally {
			entityManager.close();
		}
	}
}

N.B. If you don’t clear your EntityManager as done in line 27 above, it will fetch result from the cache and not going to get you something from database.

And we are done, pom.xml will remain the same as in earlier post, so is persistence.xml.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s