Hibernate by Example – Part 2 (DetachedCriteria)

So last time we helped out justice league to effectively manager their super heroes. Today we focus on how The Avengers will be using Hibernate’s Detached Criteria to find out their enemies with respect to each superhero so as to protect their super heroes.

You can download the working example from here.

In this example we take only two entities into consideration. The Avenger & The Villain. We build a relationship between the two using a join table. Let us have a look at the domain mappings used in this example.

package com.avengers.domain;
 
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
 
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
 
import org.hibernate.annotations.Type;
 
/**
 * The domain class representing each member of the avengers
 * 
 * @author Dinuka.Arseculeratne
 * 
 */
@Entity
@Table(name = "Avengers")
public class Avenger implements Serializable {
 
 /**
  * The primary key of the Avenger table
  */
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "avenger_id")
 private Long avengerId;
 
 /**
  * The name of the avenger member
  */
 @Column(name = "avenger_name")
 private String avengerName;
 
 /**
  * A flag which holds whether the avenger's powers are awesome
  */
 @Type(type = "yes_no")
 @Column(name = "is_awesome")
 private boolean isAwesome;
 
 /**
  * The list of enemies the avenger has
  */
 @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
 @JoinTable(name = "AVENGERS_AND_VILLAINS", joinColumns = { @JoinColumn(name = "avenger_id") }, inverseJoinColumns = { @JoinColumn(name = "villain_id") })
 private List<Villain> enemyList = new ArrayList<Villain>();
 
 public Long getAvengerId() {
  return avengerId;
 }
 
 public void setAvengerId(Long avengerId) {
  this.avengerId = avengerId;
 }
 
 public String getAvengerName() {
  return avengerName;
 }
 
 public void setAvengerName(String avengerName) {
  this.avengerName = avengerName;
 }
 
 public boolean isAwesome() {
  return isAwesome;
 }
 
 public void setAwesome(boolean isAwesome) {
  this.isAwesome = isAwesome;
 }
 
 public List<Villain> getEnemyList() {
  return enemyList;
 }
 
 public void addEnemy(Villain enemy) {
  enemyList.add(enemy);
 }
 
 @Override
 public String toString() {
  return "Avenger [avengerId=" + avengerId + ", avengerName="
    + avengerName + ", isAwesome=" + isAwesome + ", enemyList="
    + enemyList + "]";
 }
 
 
}
 

This class maps an avenger. I have used minimal fields in order to keep this example as simple and short as possible. And the Villain domain looks as follows;

package com.avengers.domain;
 
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.Table;
 
import org.hibernate.annotations.Type;
 
/**
 * This class represents the Villain forces against the avengers
 * 
 * @author Dinuka.Arseculeratne
 * 
 */
@Entity
@Table(name = "Villains")
public class Villain implements Serializable {
 
 /**
  * The primary key of the Enemy table
  */
 @Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "villain_id")
 private Long villaiId;
 
 /**
  * The name of the enemy
  */
 @Column(name = "villain_name")
 private String villainName;
 
 /**
  * A flag which checks whether the villain is super awesome
  */
 @Type(type = "yes_no")
 @Column(name = "is_awesome")
 private boolean isAwesome;
 
 public Long getVillaidId() {
  return villaiId;
 }
 
 public void setVillaidId(Long villaidId) {
  this.villaiId = villaidId;
 }
 
 public String getVillainName() {
  return villainName;
 }
 
 public void setVillainName(String villainName) {
  this.villainName = villainName;
 }
 
 public boolean isAwesome() {
  return isAwesome;
 }
 
 public void setAwesome(boolean isAwesome) {
  this.isAwesome = isAwesome;
 }
 
 @Override
 public String toString() {
  return "Villain [villaiId=" + villaiId + ", villainName=" + villainName
    + ", isAwesome=" + isAwesome + "]";
 }
 
}

Ok now that we have defined our domains, let us see how data retrieval happens with DetachedCriteria. I have used DetachedCriteria here because The Avengers were very specific and said they do not want anything to do with the Hibernate session, so hence i used DetachedCriteria which does not require a hibernate session to be present.

Our primary objective is to retrieve The Avenger to whom a villain belongs to. Note that this assumes the same villain cannot be a villain to more than one superhero. So moving on i give below the method that retrieves an avenger based on the villain name passed.

public Avenger retrieveAvengerByVillainName(String villainName) {
 
  Avenger avenger = null;
  /**
   * Selected a detached criteria so we do not need a session to run it
   * within.
   */
  DetachedCriteria criteria = DetachedCriteria.forClass(Avenger.class);
 
  /**
   * Here we are doing an inner join with the Villain table in order to do
   * a name comparison with the villainName passed in as a method
   * parameter
   */
  DetachedCriteria villainCriteria = criteria.createCriteria("enemyList");
 
  villainCriteria.add(Restrictions.eq("villainName", villainName));
 
  villainCriteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
 
  @SuppressWarnings("unchecked")
  List<Avenger> avengerList = getHibernateTemplate().findByCriteria(
    criteria);
 
  if (!avengerList.isEmpty()) {
   avenger = avengerList.get(0);
   getHibernateTemplate().initialize(avenger.getEnemyList());
  }
  return avenger;
 
 }

In this method what we do is first we create a criteria for our master class which in this case is Avenger.class. Then we need to do a join with the Villain table and hence we create a sub criteria from our main criteria with the name of the list we defined within the Avenger domain class.

Then it is a matter of equaling the property of the Villain domain to the villain name passed in.

The power of the Criteria API is such that you can create dynamic queries with ease which would be a hassle if we were to use pure HQL which would require substantial string concatenations in order to achieve the same.

A sample test class called AvengerTest.java is given with the attachment which you can find at the top of the most. Note that you need to remove the comment on avenger-context.xml in order to create the tables needed for this example.

So that is about it.

The Avengers can be risk averse now that they have a system by which they can relate any super villain to a super hero within their league.

As always your comments and suggestions are always welcome and appreciated.

Thank you for taking the time to read!!!!

Reference: Hibernate by Example – Part 2 (DetachedCriteria) from our JCG partner Dinuka Arseculeratne  at the My Journey Through IT blog

Related Articles :

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

Leave a Reply


seven + = 15



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close