Criteria with Projection

In Hibernate-Criteria article , we have learned about Criteria where we use to load entire object based on certain restrictions.

Projections will become handy when we want to load the partial object.

Partial object means only few attributes will be loaded rather than all the attributes.

In some cases, it is unnecessary to load all the attributes of an object.

Main points to remember about Projections


Projection is an Interface defined in “org.hibernate.criterion” package

Projections is a class and it is a factory for producing the projection objects.

Projection is mainly used to retrieve partial object.

To add a Projection object to Criteria , we need to call a setProjection() method on Criteria.

We can add as many projection objects as we want but only latest object will be considered, so no use in adding multiple projection objects to criteria.

We need to create one projection object for specifying one property.

If we want more than one property to be included in the result, then we need to create multiple Projection objects one for each property and add all of them to ProjectionList and then we need to set ProjectionList object to Criteria.

Example:
Below example illustrates retrieving only one column of a table using Projection.

1
2
3
4
Criteria criteria = session.createCriteria(Employee.class);
Projection projection = Projections.property(“firstName”);
criteria.setProjection(projection);
List list = criteria.list();
Criteria criteria = session.createCriteria(Employee.class);
Projection projection = Projections.property(“firstName”);
criteria.setProjection(projection);
List list = criteria.list();

In the above example, we applied Projection on only one property “FirstName”.

The equivalent SQL query is “select firstName from Employee”.

If we want to apply projections to retrieve multiple properties, we can use ProjectionList as shown below

1
2
3
4
5
6
7
8
9
10
11
Criteria criteria = session.createCriteria(Employee.class);
Projection projection1 = Projections.property(“firstName”);
Projection projection2 = Projections.property(“salary”);
Projection projection3 = Projections.property(“age”);
 
ProjectionList projectionList = Projections.projectionList();
projectionList.add(projection1);
projectionList.add(projection2);
projectionList.add(projection3);
criteria.setProjection(projectionList);
List list = criteria.list();
Criteria criteria = session.createCriteria(Employee.class);
Projection projection1 = Projections.property(“firstName”);
Projection projection2 = Projections.property(“salary”);
Projection projection3 = Projections.property(“age”);

ProjectionList projectionList = Projections.projectionList();
projectionList.add(projection1);
projectionList.add(projection2);
projectionList.add(projection3);
criteria.setProjection(projectionList);
List list = criteria.list();


Lets see the complete project on projections

Step 1

Create hibernate project

Please refer Hibernate setup in eclipse article on how to do it.

Project structure

Projections_ProjStructure

Step 2

Update pom.xml with Hibernate and Mysql dependencies

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
 
  <groupId>HibernateProjections</groupId>
  <artifactId>HibernateProjections</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
 
  <name>HibernateProjections</name>
  <url>http://maven.apache.org</url>
 
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
 
  <dependencies>
 
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
     <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>5.2.6.Final</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>6.0.5</version>
        </dependency>
 
  </dependencies>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>HibernateProjections</groupId>
  <artifactId>HibernateProjections</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>HibernateProjections</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
     <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>5.2.6.Final</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>6.0.5</version>
		</dependency>

  </dependencies>
</project>

Step 3

Create Employee class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package com.kb.model;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
 
@Entity
@Table(name="Employee")
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "Employee_Id")
    private int employeeId;
    
    @Column(name = "FirstName")
    private String firstName;
    
    @Column(name = "LastName")
    private String lastName;
    
    @Column(name = "Age")
    private int age;
    
    @Column(name = "Education")
    private String education;
    
    @Column(name = "Salary")
    private int salary;
    
    public int getEmployeeId() {
        return employeeId;
    }
    public void setEmployeeId(int employeeId) {
        this.employeeId = employeeId;
    }
    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 int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getEducation() {
        return education;
    }
    public void setEducation(String education) {
        this.education = education;
    }
    public int getSalary() {
        return salary;
    }
    public void setSalary(int salary) {
        this.salary = salary;
    }
}
package com.kb.model;

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

@Entity
@Table(name="Employee")
public class Employee {
	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE)
	@Column(name = "Employee_Id")
	private int employeeId;
	
	@Column(name = "FirstName")
	private String firstName;
	
	@Column(name = "LastName")
	private String lastName;
	
	@Column(name = "Age")
	private int age;
	
	@Column(name = "Education")
	private String education;
	
	@Column(name = "Salary")
	private int salary;
	
	public int getEmployeeId() {
		return employeeId;
	}
	public void setEmployeeId(int employeeId) {
		this.employeeId = employeeId;
	}
	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 int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getEducation() {
		return education;
	}
	public void setEducation(String education) {
		this.education = education;
	}
	public int getSalary() {
		return salary;
	}
	public void setSalary(int salary) {
		this.salary = salary;
	}
}

We have specified Primary key as employeeId and generator class as “sequence” for automatic primary key generation.

Step 4

Create hibernate.cfg.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?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 properties -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost/javainsimpleway</property>
        <property name="connection.username">root</property>
        <property name="connection.password">root</property>
 
        <!-- JDBC connection pool (using the built-in) -->
        <property name="connection.pool_size">100</property>
 
        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
 
        <!-- Disable the second-level cache -->
        <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>
 
        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>
 
        <!-- Format the generated Sql -->
        <property name="format_sql">false</property>
 
        <!-- Dont Drop and re-create the database schema on startup,Just update 
            it -->
        <property name="hbm2ddl.auto">update</property>
 
        <mapping class="com.kb.model.Employee" />
 
    </session-factory>
 
</hibernate-configuration>
<?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 properties -->
		<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="connection.url">jdbc:mysql://localhost/javainsimpleway</property>
		<property name="connection.username">root</property>
		<property name="connection.password">root</property>

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

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

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

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

		<!-- Format the generated Sql -->
		<property name="format_sql">false</property>

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

		<mapping class="com.kb.model.Employee" />

	</session-factory>

</hibernate-configuration>


We have defined all the database configuration in this file

hbm2ddl.auto property is defined in the config file which helps in automatic creation of tables in the database based on the mapping.

We have also provided the mapping class name using “mapping” tag.

Step 5

Create Hibernate util class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.kb.util;
 
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
 
public class HibernateUtil {
    private static final SessionFactory sessionFactory = buildSessionFactory();
 
    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Make sure you log the exception to track it
            System.err.println("SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }
 
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
    
    public static void shutdown() {
        // Optional but can be used to Close caches and connection pools
        getSessionFactory().close();
    }
 
}
package com.kb.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
	private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Make sure you log the exception to track it
            System.err.println("SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
    
    public static void shutdown() {
    	// Optional but can be used to Close caches and connection pools
    	getSessionFactory().close();
    }

}

Step 6

Create PopulateData.java file to Populate Employee Table with initial data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.kb.db;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
 
import com.kb.model.Employee;
import com.kb.util.HibernateUtil;
 
public class PopulateData {
public static void main(String[] args) {
 
    // Get session factory using Hibernate Util class
    SessionFactory sf = HibernateUtil.getSessionFactory();
    // Get session from Sesson factory
    Session session = sf.openSession();
 
    // Begin transaction
    Transaction t = session.beginTransaction();
    
    //Create Employee  data
    Employee employee1 = new Employee();
    employee1.setFirstName("John");
    employee1.setLastName("KC");
    employee1.setAge(28);
    employee1.setEducation("PG");
    employee1.setSalary(25000);
    
    Employee employee2 = new Employee();
    employee2.setFirstName("Jacob");
    employee2.setLastName("JC");
    employee2.setAge(30);
    employee2.setEducation("PG");
    employee2.setSalary(30000);
    
    Employee employee3 = new Employee();
    employee3.setFirstName("Martin");
    employee3.setLastName("A");
    employee3.setAge(24);
    employee3.setEducation("UG");
    employee3.setSalary(20000);
    
    Employee employee4 = new Employee();
    employee4.setFirstName("Peter");
    employee4.setLastName("M");
    employee4.setAge(25);
    employee4.setEducation("UG");
    employee4.setSalary(22000);
    
    Employee employee5 = new Employee();
    employee5.setFirstName("Roshan");
    employee5.setLastName("B");
    employee5.setAge(29);
    employee5.setEducation("PG");
    employee5.setSalary(45000);
    
    
    session.save(employee1);
    session.save(employee2);
    session.save(employee3);
    session.save(employee4);
    session.save(employee5);
 
    // Commit the transaction and close the session
    t.commit();
    
    session.close();
    System.out.println("successfully persisted Employee details");
 
   }
 
}
package com.kb.db;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;

import com.kb.model.Employee;
import com.kb.util.HibernateUtil;

public class PopulateData {
public static void main(String[] args) {

	// Get session factory using Hibernate Util class
	SessionFactory sf = HibernateUtil.getSessionFactory();
	// Get session from Sesson factory
	Session session = sf.openSession();

	// Begin transaction
	Transaction t = session.beginTransaction();
	
	//Create Employee  data
	Employee employee1 = new Employee();
	employee1.setFirstName("John");
	employee1.setLastName("KC");
	employee1.setAge(28);
	employee1.setEducation("PG");
	employee1.setSalary(25000);
	
	Employee employee2 = new Employee();
	employee2.setFirstName("Jacob");
	employee2.setLastName("JC");
	employee2.setAge(30);
	employee2.setEducation("PG");
	employee2.setSalary(30000);
	
	Employee employee3 = new Employee();
	employee3.setFirstName("Martin");
	employee3.setLastName("A");
	employee3.setAge(24);
	employee3.setEducation("UG");
	employee3.setSalary(20000);
	
	Employee employee4 = new Employee();
	employee4.setFirstName("Peter");
	employee4.setLastName("M");
	employee4.setAge(25);
	employee4.setEducation("UG");
	employee4.setSalary(22000);
	
	Employee employee5 = new Employee();
	employee5.setFirstName("Roshan");
	employee5.setLastName("B");
	employee5.setAge(29);
	employee5.setEducation("PG");
	employee5.setSalary(45000);
	
	
	session.save(employee1);
	session.save(employee2);
	session.save(employee3);
	session.save(employee4);
	session.save(employee5);

	// Commit the transaction and close the session
	t.commit();
	
	session.close();
	System.out.println("successfully persisted Employee details");

   }

}

In this class, we are persisting 5 Employee records

Step 7

Lets Create Main class to perform projection operations

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package com.kb.db;
 
import java.util.Iterator;
import java.util.List;
 
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
 
import com.kb.model.Employee;
import com.kb.util.HibernateUtil;
 
public class ProjectionExample {
    @SuppressWarnings("deprecation")
    public static void main(String[] args) {
        SessionFactory sf = HibernateUtil.getSessionFactory();
        Session session = sf.openSession();
 
        Criteria criteria = session.createCriteria(Employee.class);
        Projection projection = Projections.property("firstName");
        criteria.setProjection(projection);
        List<String> firstNameList = criteria.list();
        System.out.println("All Employee records with only first name column");
        for (String firstName : firstNameList) {
            System.out.println("First Name :" + firstName);
        }
 
        criteria = session.createCriteria(Employee.class);
        Projection projection1 = Projections.property("firstName");
        Projection projection2 = Projections.property("salary");
        Projection projection3 = Projections.property("age");
 
        ProjectionList projectionList = Projections.projectionList();
        projectionList.add(projection1);
        projectionList.add(projection2);
        projectionList.add(projection3);
 
        criteria.setProjection(projectionList);
 
        List empList = criteria.list();
 
        System.out.println("All the empoyees with first name,salary and age columns");
        Iterator iterator = empList.iterator();
 
        while (iterator.hasNext()) {
            Object[] obj = (Object[]) iterator.next();
            System.out.println("First Name" + obj[0] + " Salary : " + obj[1] + " Age : " + obj[2]);
        }
 
        criteria = session.createCriteria(Employee.class);
        criteria.setProjection(Projections.rowCount());
        List<Long> result = criteria.list();
        System.out.println("Total number of employees :" + result);
 
        criteria = session.createCriteria(Employee.class);
        double sumSalary = (Long)               
                    session.createCriteria(Employee.class).setProjection(Projections.sum("salary")).uniqueResult();
        System.out.println("Sum of Salary of all employees : " + sumSalary);
 
        // Adding both restrictions and projection on criteria
        criteria = session.createCriteria(Employee.class);
        criteria.add(Restrictions.gt("age", 25));
        criteria.setProjection(projectionList);
        empList = criteria.list();
        Iterator iterator1 = empList.iterator();
                System.out.println("All employees whose age is greater than 25");
        while (iterator1.hasNext()) {
            Object[] obj = (Object[]) iterator1.next();
            System.out.println("First Name" + obj[0] + " Salary : " + obj[1] + " Age : " + obj[2]);
        }
 
        session.close();
    }
 
}
package com.kb.db;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import com.kb.model.Employee;
import com.kb.util.HibernateUtil;

public class ProjectionExample {
	@SuppressWarnings("deprecation")
	public static void main(String[] args) {
		SessionFactory sf = HibernateUtil.getSessionFactory();
		Session session = sf.openSession();

		Criteria criteria = session.createCriteria(Employee.class);
		Projection projection = Projections.property("firstName");
		criteria.setProjection(projection);
		List<String> firstNameList = criteria.list();
		System.out.println("All Employee records with only first name column");
		for (String firstName : firstNameList) {
			System.out.println("First Name :" + firstName);
		}

		criteria = session.createCriteria(Employee.class);
		Projection projection1 = Projections.property("firstName");
		Projection projection2 = Projections.property("salary");
		Projection projection3 = Projections.property("age");

		ProjectionList projectionList = Projections.projectionList();
		projectionList.add(projection1);
		projectionList.add(projection2);
		projectionList.add(projection3);

		criteria.setProjection(projectionList);

		List empList = criteria.list();

		System.out.println("All the empoyees with first name,salary and age columns");
		Iterator iterator = empList.iterator();

		while (iterator.hasNext()) {
			Object[] obj = (Object[]) iterator.next();
			System.out.println("First Name" + obj[0] + " Salary : " + obj[1] + " Age : " + obj[2]);
		}

		criteria = session.createCriteria(Employee.class);
		criteria.setProjection(Projections.rowCount());
		List<Long> result = criteria.list();
		System.out.println("Total number of employees :" + result);

		criteria = session.createCriteria(Employee.class);
		double sumSalary = (Long)               
                    session.createCriteria(Employee.class).setProjection(Projections.sum("salary")).uniqueResult();
		System.out.println("Sum of Salary of all employees : " + sumSalary);

		// Adding both restrictions and projection on criteria
		criteria = session.createCriteria(Employee.class);
		criteria.add(Restrictions.gt("age", 25));
		criteria.setProjection(projectionList);
		empList = criteria.list();
		Iterator iterator1 = empList.iterator();
                System.out.println("All employees whose age is greater than 25");
		while (iterator1.hasNext()) {
			Object[] obj = (Object[]) iterator1.next();
			System.out.println("First Name" + obj[0] + " Salary : " + obj[1] + " Age : " + obj[2]);
		}

		session.close();
	}

}

Step 8

Run PopulateData.java class to create the initial data

Step 9

Check the output in MYSQL DB

E:\MySql_Install\bin
Mysql –u root –p
Enter password

Use javainsimpleway;

Select * from Employee;

populateAggregateDataOutput

We can see that Emploeyee table has 5 records.

Step 10

Run ProjectionExample.java

Output


Download this project HibernateProjections.zip

About the Author

Karibasappa G C (KB)
Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on