Understanding and preventing memory leaks in Java

For any developer, memory should be one of the most precious resources to think of while writing a program. A program can be said to be memory efficient when it consumes as little memory as possible when in operation but still doing what it was designed to do. So, before write code think of memory uses, do you know What happens when a Java object is created?

What is a Memory Leak?

In simple words, memory leak means unused memory that the garbage collectors can not reclaim.

A memory leak occurs when objects are no longer being used by the application, but the garbage collector is unable to clear them from working memory. This is a serious problem because these objects hold the memory that could otherwise be used by other parts of the program. With time, this piles up and leads to a degradation in system performance over time.

Garbage Collection in Java

One of the coolest features of Java is its automatic memory management. The Garbage Collection is a program that implicitly takes care of memory allocation and deallocation. It’s an effective program and can handle the majority of memory leaks that are likely to occur. However, it’s not infallible. Memory leaks can still sneak up and start taking up precious resources and, in worst cases, result in the java.lang.OutOfMemoryError.

It’s worth mentioning that an OutOfMemoryError is not always because of memory leaks. At times, it could be poor code practices like loading large files in memory.

The three common causes of memory leaks?

  • Misused static fields
  • Un closed streams
  • Un closed connections

Misused static fields

Static fields live in the memory as long as the class that owns them is loaded in the JVM, which means there are no instances of the class in the JVM, at this point, the class will be unloaded and the static field will be marked for garbage collection. But the catch here is, the static classes can live in the memory forever.

Consider the following code:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class StaticDemo {
public static List<Integer> list = new ArrayList<>();

public void populateList() {
for (int i = 0; i < 10000000; i++) {
   list.add(new Random().nextInt());
}
}
public static void main(String[] args) {
  new StaticDemo().populateList();
}
}

This is a simple and small code snippet, we have a static List and we added values into it. But If we see the declaration of the list we have used static in front of it.  That’s the problem, the memory occupied by this list will be in use until the program finishes its execution even though the operations on the list are already completed.

To avoid this mistake, Minimize the use of static fields in your application.

Un closed streams

Till now we have understood memory leak is when code holds a reference to an object and the garbage collector can’t claim that object. But, a closed stream object is not memory unless it holds a reference of an unclosed stream.

Usually, the operating system limits how many open files (while using FileInputStream) an application can have. So, if such streams are not closed and the garbage collector may take some to claim these objects, it is also a case of the leak but not particularly a memory leak.

Refer to the following code snippet:

import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;

public class OpenStreamDemo {

    public static void main(String[] args) throws IOException {
        URL url = new URL("http://ergast.com/api/f1/2004/1/results.json");
        ReadableByteChannel rbc = Channels.newChannel(url.openStream());
        FileOutputStream outputStream = new FileOutputStream("/");
        outputStream.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
    }
}

Here the unclosed FileOutputStream and ReadableByteChannel will cause potential issues. The solution to this problem would be closing these stream objects once they are used and not require further. Or use java to try with resources wherever allowed.

rbc.close();
outputStream.close();

Un closed connections

The frequent mistake in Java programming is, developer forgot to close the database connections.  Having an unclosed database connection can give you a tough time in production and they are difficult to replicate in local environments.

Refer to the below code snippet:

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class OpenConnectionDemo {

    public static void main(String[] args) {
        try {
            List<String> names = fetchUsersName("foo", "bar");
            names.forEach(System.out::println);

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static List<String> fetchUsersName(String username, String password) throws SQLException {
        List<String> names = new ArrayList<>();
        Connection con = DriverManager.getConnection("jdbc:myDriver:devDB",
                username,
                password);

        Statement stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT first_name, last_name FROM users");

        String firstName = "";
        String lastName = "";

        while (rs.next()) {
            firstName = rs.getString("first_name");
            lastName = rs.getString("last_name");
            names.add(firstName + " " + lastName);
        }
        return names;
    }
}

Here every resource is leaking. Here we could have use try-catch and finally, and inside the finally block we can close

stmt.close();
con.close();

Here is the complete code for the fetchUsersName method.

public static List<String> fetchUsersName(String username, String password) throws SQLException {
    Statement stmt = null;
    Connection con = null;
    List<String> names = new ArrayList<>();
    try {

        con = DriverManager.getConnection("jdbc:myDriver:devDB",
                username,
                password);

        stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT first_name, last_name FROM users");

        String firstName = "";
        String lastName = "";

        while (rs.next()) {
            firstName = rs.getString("first_name");
            lastName = rs.getString("last_name");
            names.add(firstName + " " + lastName);
        }
    }catch (SQLException se){
        se.printStackTrace();
    }finally {
        stmt.close();
        con.close();
    }
    return names;
}

Or we can use try with resources like below.

public static List<String> fetchUsersName(String username, String password) throws SQLException {
    List<String> names = new ArrayList<>();
    try (Connection con = DriverManager.getConnection("jdbc:myDriver:devDB",username,password);
         Statement stmt = con.createStatement();
    ){
        ResultSet rs = stmt.executeQuery("SELECT first_name, last_name FROM users");

        String firstName = "";
        String lastName = "";

        while (rs.next()) {
            firstName = rs.getString("first_name");
            lastName = rs.getString("last_name");
            names.add(firstName + " " + lastName);
        }
    }catch (SQLException se){
        se.printStackTrace();
    }
    return names;
}

We can also use ORM like hibernate or jooq which provides easier and more maintainable resource handling.

So the take away from this post are:

  1. Be careful while using static fields.
  2. Make sure to close the stream and connection or use try with resources.
  3. Use ORM if your application allows.

 

Happy Learning !!!

Database transaction Isolation Levels and their effect

In this tutorial we will discuss the database transaction Isolation Levels, types of database transaction Isolation Levels, and their impact.

When as a developer we start developing an application to manage the data we use a database. But do we know about the job databases perform apart from executing the queries, particularly their efforts to maintain the Isolation aspect of ACID? For example, the transactions are only related to data manipulation and not to queries, which is an incorrect assumption. Transaction Isolation is all about queries, and the consistency and completeness of the data retrieved by queries. This is how it works.

Isolation gives the querying user the feeling that he owns the database. It does not matter how many concurrent users work with the same database and the same schema or even the same data. These other uses can generate new data, modify existing data, or perform any other action. The querying user must be able to get a complete, consistent picture of the data, unaffected by other users’ actions.

Consider the following scenario, which is based on a Customer table that has 1,000,000 rows:

  • At, 9:00: User A started a query “SELECT * FROM Customer”, which queries all the rows of the table. Suppose, this query takes approximately five minutes to complete, as the database must fully scan the table’s blocks from start to end and extract the rows. This is called a FULL TABLE SCAN query and is not recommended from a performance perspective.
  • 9:01: User B updates the last row in the Customer table, and commits the change.
  • 9:04: User A’s query process arrives at the row modified by User B. what will happen?

Any guess? Will User A get the original row value or the new row value? The new row value is legitimate and committed, but it was updated after User A’s query started.

The answer is not very clear and completely depends on the isolation level of the transaction. There are four types of isolation levels, as follows:

Read Uncommitted

The changes made by User B will be available for User A. This isolation level is called dirty reads, which means that read data is not consistent with other parts of the table or the query and may not yet have been committed. Therefore this isolation level ensures the quickest performance, as data is read directly from the table’s blocks with no further processing, verification, or any other validation. The process is quick and the data is as dirty as it can get.

In read committed isolation level, User A will see the changes made by user B even if user B has not yet committed the changes.

Read Committed

User A will not see the change made by User B. This is because in the Read Committed isolation level, the rows returned by a query are the rows that were committed when the query was started. The change made by User B was not present when the query started, and therefore will not be included in the query result.

Repeatable Read

User B changes will not be visible to User A. This is because, in the Repeatable Read isolation level, the rows returned by a query are the rows that were committed when the transaction was started. The change made by User B was not present when the transaction was started, and therefore will not be included in the query result.

Serializable

This isolation level specifies that all transactions occur in a completely isolated fashion, meaning as if all transactions in the system were executed serially, one after the other. The DBMS can execute two or more transactions at the same time only if the illusion of serial execution can be maintained.

Reference

Isolation (database_systems)
Database isolation levels and their effects on performance

Happy Learning !!

The N+1 Query Problem example with hibernate

Mostly while developing an application we (developers) do not consider the performance indexes, which really would not be an area of concern at that time. But when the application needs to scale and optimized these performance indexes come into the picture. Then the developers need to focus on how the application can be optimized and refactored to improve the performance.

One major area for improvement is the number of queries the application executes on the database. Reduce the number of queries to improve application performance.

Most applications are designed to distribute the data over many models with associations between them and uses ORMs for access. ORMs can help you to address the impedance mismatch between relational databases and object-oriented models, hopefully making your life simpler. But not knowing about some of their pitfalls can decrease your application performance dramatically. One such pitfall is the select N+1 problem.

Read the Advantages of using ORM and the reason to choose ORM over JDBC.

What is the N+1 Query Problem?

As the mapping between tables is represented as associations between classes. This problem occurs when the code needs to load the parent-child relationship (i.e. One-to-Many). Most ORMs have lazy loading enabled by default, so the queries are executed to load the parent records and then one query for each child record. This is the N+1 problem. As you can expect to do N+1 instead of a single query will flood the database with queries, which is something we should avoid.

Consider the following example.
Let’s assume that you are writing code that maintains the post and the user posting them. Now let say you have a class representing Users and each user has a collection of Posts.

To keep it simple, we can say there is a one-to-many relationship between User and Post like below.

public class User {

 int userid;
 String name;
 
 List<Post> posts;
 
 }

public class Post {
 
	int postId;
	String title;
	Date postedOn;
	User user;
	
}

Now suppose you need to print all the posts by all the users. One solution using ORM would be to select all Users in one query and then do N additional select to fetch the posts by each user like below.

-- fetch all users
select * from User;

-- fetch all posts by user
select * from Post where User.userid =?

As you can see, the N+1 problem can happen if the first query populates the primary object and the second query populates all the child objects for each of the unique primary objects returned.

Solution for N+1 SELECTs problem:

  • Eager loading
  • Using the join clause

If you are using Hibernate as an ORM you can apply the following solutions.

1. Using HQL fetch join

from User u join fetch u.posts posts

2. Criteria Query

Criteria criteria = session.createCriteria(User.class);

criteria.setFetchMode("posts", FetchMode.EAGER);

In both cases, our query returns a list of User objects with the posts initialized. Only one query is used to fetch all the posts and user information.

Happy Learning !!

Recommended Read

Hibernate

Reference

Diagnosing and Resolving Problems

java.lang.IllegalArgumentException

Problem: Using Hibernate 5.0.5, but hits this java.lang.IllegalArgumentException: node to traverse cannot be null! exception, refer the below error stacks:

line 1:8: unexpected token: in
	at org.hibernate.hql.internal.antlr.HqlBaseParser.updateStatement(HqlBaseParser.java:239)
	at org.hibernate.hql.internal.antlr.HqlBaseParser.statement(HqlBaseParser.java:169)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:279)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:187)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:142)
	at org.hibernate.engine.query.spi.HQLQueryPlan.&lt;init&gt;(HQLQueryPlan.java:115)
	at org.hibernate.engine.query.spi.HQLQueryPlan.&lt;init&gt;(HQLQueryPlan.java:76)
	at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:150)
	at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:302)
	at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:240)
	at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1894)
	at com.codersdesks.hibernate.main.MainApp.main(MainApp.java:21)

Exception in thread "main" java.lang.IllegalArgumentException: node to traverse cannot be null!
	at org.hibernate.hql.internal.ast.util.NodeTraverser.traverseDepthFirst(NodeTraverser.java:46)
	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:284)
	

Solution:

This is a generic Hibernate error message indicating a syntax problem in your query. One example of this is shown below.

If you are missing from the clause then also found the same issues.

Wrong Query-

String query=” user where lid=? and lmt=?”;

Right Query-

String query=” from user where lid=? and lmt=?”;

This error also commonly happens when you use the method createQuery to run a named query, instead of getNamedQuery.

You may face this issue when using the HQL query to update the records and our package name in which entity class resides start with some SQL reserved keywords. i.e. in

like in my case the package name starting with ‘in’ receive “unexpected token: in”.

In this either change the package name if your application allows or user native SQL query or load the entity and the update itself.

Recommended Read:

Hibernate CRUD operations
Hibernate Architecture
Commonly used methods of org.hibernate.Session Interface.

Hibernate Doc

Happy Learning !!

java.lang.ClassNotFoundException : javassist.util.proxy.MethodFilter

Problem:

Using Hibernate 5.0.5, but hits this javassist not found error, refer to the below error stacks :

Caused by: java.lang.NoClassDefFoundError: javassist/util/proxy/MethodFilter
	at org.hibernate.bytecode.internal.javassist.BytecodeProviderImpl.getProxyFactoryFactory(BytecodeProviderImpl.java:41)
	at org.hibernate.tuple.entity.PojoEntityTuplizer.buildProxyFactoryInternal(PojoEntityTuplizer.java:200)
	at org.hibernate.tuple.entity.PojoEntityTuplizer.buildProxyFactory(PojoEntityTuplizer.java:175)
	at org.hibernate.tuple.entity.AbstractEntityTuplizer.<init>(AbstractEntityTuplizer.java:157)
	at org.hibernate.tuple.entity.PojoEntityTuplizer.<init>(PojoEntityTuplizer.java:63)
	... 20 more
Caused by: java.lang.ClassNotFoundException: javassist.util.proxy.MethodFilter
	at java.net.URLClassLoader.findClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)
	at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
	at java.lang.ClassLoader.loadClass(Unknown Source)

Solution:

javassist.jar is missing, add the below dependency in your pom file, or download the jar from the JBoss Maven repository.

<dependency>
	<groupId>javassist</groupId>
	<artifactId>javassist</artifactId>
	<version>3.18.1.GA</version>
</dependency>

Recommended Read

Java Exception in detail with example
Java Exception Test

Happy Learning !!

ACID properties in Relation database

ACID properties are a set of properties that intended to guarantee validity even in the event of an error, power failure, etc.

ACID is shorthand for Atomicity, Consistency, Isolation, and Durability. In the context of the database, a sequence of database operations that satisfies the ACID properties is called a transaction.

ACID properties

Atomicity: Transaction is often composed of multiple statements. Atomicity guarantee that each transaction is treated as a single unit, which either successes completely or fails. In any of the statements consisting of transactions that fail to complete the entire transaction failed and the database left unchanged.

Consistency: Consistency ensures that a transaction can only bring the database from one valid state to another valid state. Any data writes to the database must be valid according to all defined rules including constraints, cascades, and triggers. Consistency ensures the data saved into the database is valid but it does not guarantee that a transaction is complete.

Isolation: Isolation generally refers to separation but in terms of database, isolation ensures that the concurrent execution of the transactions does not corrupt the data.

Durability: Durability as the name suggest that once a transaction is committed, the data will remain committed even in case of system failure. This often means that the completed transactions are recorded in non-volatile memory.

Recommended Read

The N+1 Query Problem example with hibernate
Hibernate Architecture

happy Learning !!

Different ways to obtain a session from the session factory

Every Java developer who has used hibernate to perform the database operation is well aware of the significance of the Session interface. It is the one which helps us in performing all the CRUD operations, call the stored procedures, etc. As we know the Session object is obtained from the session factory, do you know about the ways we can obtain it?

In this post, we will discuss different ways to obtain sessions from the session factory. What are the configuration changes that need to be done when using the getCurrentSession() method?

The session is a short-lived and non-thread-safe object used to perform all the database activities. The SessionFactory provides three ways to obtain a session object.

openSession()
Syntax

public Session openSession() throws HibernateException;

Hibernate SessionFactory openSession() method always opens a new session. Therefore, the session object should be closed once we are done with all the database operations. This should be used in a multi-threaded environment.

getCurrentSession()
Syntax

public Session getCurrentSession() throws HibernateException;

Hibernate SessionFactory getCurrentSession method returns the session bound to the hibernate context. But for this to work, we need to configure it in the hibernate configuration file by adding the below properties. In addition to this, the Session instance obtained through getCurrentSession method also requires an active transaction to perform any database task. Without an active transaction, it will throw org.hibernate.HibernateException.

<property name="hibernate.current_session_context_class">thread</property>

Since the session object is bound to hibernate context we don’t need to close it. Once the session factory is destroyed it will be closed automatically. As mentioned earlier the session object is not thread-safe, we should not use this in a multi-threaded environment.

openStatelessSession()
Syntax

public StatelessSession openStatelessSession();

A stateless session does not implement a first-level cache nor interact with any second-level cache, nor does it implement transactional write-behind or automatic dirty checking, nor do operations cascade to associated instances. Collections are ignored by a stateless session.

Observe the below code snippet to obtain different session instance from the session factory.

import org.hibernate.Session;
import org.hibernate.StatelessSession;
import com.hibernate.util.HibernateUtil;

public class SessionFactoryExample {


	static void testOpenSession(){
		Session session = HibernateUtil.getSessionFactory().openSession();
		
		session.close();
	}
	
	
	static void testGetCurrentSession(){
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		HibernateUtil.closeSessionFactory();
	}
	
	
	static void testOpenStatelessSession(){
		StatelessSession session = HibernateUtil.getSessionFactory().openStatelessSession();
		session.close();
	}
}

hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
		"http://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost/hibernate_dev</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">root</property>
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<property name="hibernate.show_sql">true</property>
		<property name="hbm2ddl.auto">update</property>
		<property name="hibernate.current_session_context_class">thread</property>
		
	</session-factory>
</hibernate-configuration>

HibernateUtil.java

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {

	private static SessionFactory sessionFactory = null;

	private static SessionFactory buildSessionFactory() {
		try {
			Configuration configuration = new Configuration();
			configuration.configure("hibernate.cfg.xml");

			ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
					.applySettings(configuration.getProperties()).build();
			SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
			return sessionFactory;
		} catch (Throwable ex) {
			System.err.println("SessionFactory creation failed." + ex);
			ex.printStackTrace();
			throw new ExceptionInInitializerError(ex);
		}
	}

	public static SessionFactory getSessionFactory() {
		if (sessionFactory == null)
			sessionFactory = buildSessionFactory();
		return sessionFactory;
	}
	
	public static void closeSessionFactory(){
		if(sessionFactory != null)
			sessionFactory.close();
	}
}

pom.xml

<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>hibernate4</groupId>
  <artifactId>hibernate</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>hibernate</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>
    <dependency>
  		<groupId>org.hibernate</groupId>
  		<artifactId>hibernate-core</artifactId>
  		<version>4.3.5.Final</version>
  	</dependency>
  	<dependency>
  		<groupId>mysql</groupId>
  		<artifactId>mysql-connector-java</artifactId>
  		<version>5.1.6</version>
  	</dependency>
  </dependencies>
</project>

You can get the maven dependency from the maven repository.

HAPPY LEARNING !!

Commonly used methods of Session Interface

The org.hibernate.Session interface is the most used interface in hibernate. It is used to perform the CURD operation. Following are the some commonly used methods of Session Interface.

Required:

  • MySQL 5.1.6
  • Java 8 (jdk 1.8)
  • Hiberante 4.3.5

Dependencies, pom.xml file

<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>hibernate4</groupId>
  <artifactId>hibernate</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>hibernate</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>
    <dependency>
  		<groupId>org.hibernate</groupId>
  		<artifactId>hibernate-core</artifactId>
  		<version>4.3.5.Final</version>
  	</dependency>
  	<dependency>
  		<groupId>mysql</groupId>
  		<artifactId>mysql-connector-java</artifactId>
  		<version>5.1.6</version>
  	</dependency>
  </dependencies>
</project>

Let’s create a table and entity class to examine each method in details.

Database Table

CREATE  TABLE `orders` (

  `orderNo` INT NOT NULL AUTO_INCREMENT ,

  `orderBy` VARCHAR(45) NOT NULL ,

  `orderDate` TIMESTAMP NOT NULL ,

  `orderAmount` DECIMAL(16,2) NULL ,

  PRIMARY KEY (`orderNo`) );

Entity class

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@Table(name="orders")
public class Orders implements Serializable{

	private static final long serialVersionUID = -7290073664502187027L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Integer orderNo;
	
	private String orderBy;
	@Temporal(value = TemporalType.TIMESTAMP)
	private Date orderDate;
	
	private Double order amount;

	public Orders() {
		super();
	}

	public Orders(String orderBy, Date orderDate, Double orderAmount) {
		super();
		this.orderBy = orderBy;
		this.orderDate = orderDate;
		this.orderAmount = orderAmount;
	}


	public Integer getOrderNo() {
		return orderNo;
	}

	public void setOrderNo(Integer orderNo) {
		this.orderNo = orderNo;
	}

	public String getOrderBy() {
		return orderBy;
	}

	public void setOrderBy(String orderBy) {
		this.orderBy = orderBy;
	}

	public Date getOrderDate() {
		return orderDate;
	}

	public void setOrderDate(Date orderDate) {
		this.orderDate = orderDate;
	}

	public Double getOrderAmount() {
		return orderAmount;
	}

	public void setOrderAmount(Double orderAmount) {
		this.orderAmount = orderAmount;
	}

	@Override
	public String toString() {
		return "Orders [orderNo=" + orderNo + ", orderBy=" + orderBy + ", orderDate=" + orderDate + ", orderAmount="
				+ orderAmount + "]";
	}	
}

Create an XML file as “hibernate.cfg.xml” under src/main/resources as below.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
		"http://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost/hibernate_dev</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">root</property>
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<property name="hibernate.show_sql">true</property>
		<property name="hbm2ddl.auto">update</property>
		<mapping class="com.hibernate.entity.Orders"/>
	</session-factory>
</hibernate-configuration>

Write a class HibernateUtil.java to create the SessionFactory instance.

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {

	private static SessionFactory sessionFactory = null;

	private static SessionFactory buildSessionFactory() {
		try {
			Configuration configuration = new Configuration();
			configuration.configure("hibernate.cfg.xml");

			ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
					.applySettings(configuration.getProperties()).build();
			SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
			return sessionFactory;
		} catch (Throwable ex) {
			System.err.println("SessionFactory creation failed." + ex);
			ex.printStackTrace();
			throw new ExceptionInInitializerError(ex);
		}
	}

	public static SessionFactory getSessionFactory() {
		if (sessionFactory == null)
			sessionFactory = buildSessionFactory();
		return sessionFactory;
	}
}

save():

Syntax:

public Serializable save(Object object);

Persist the given transient instance, first assigning a generated identifier or using the current value of the identifier property if the assigned generator is used.

Let’s see the below code snippet to save a transient object into the database.

import java.util.Date;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.hibernate.entity.Orders;
import com.hibernate.util.HibernateUtil;

public class SessionInterfaceMethods {

	public static void main(String[] args) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		
		Orders order = new Orders("Ram", new Date(), 1000.50);
		
		Transaction t = session.beginTransaction();
		
		session.save(order);
		t.commit();
		session.close();	
	}
}

when you run the above code it will insert a record into the database.

Hibernate: insert into orders (orderAmount, orderBy, orderDate) values (?, ?, ?)

We can retrieve the generated ID for the object using the save method. As shown in the save method syntax it returns Serializable.

Let’s modify the above code to retrieve the generated ID.

import java.util.Date;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.hibernate.entity.Orders;
import com.hibernate.util.HibernateUtil;

public class SessionInterfaceMethods {

	public static void main(String[] args) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		
		Orders order = new Orders("kamal", new Date(), 1100.50);
		
		Transaction t = session.beginTransaction();
		
		Integer ID = (Integer) session.save(order);
		System.out.println("generated id is : "+ID);
		t.commit();
		session.close();
		
	}
}

The output of the above code snippet:
output

persist():

Syntax:

public void persist(Object object);

Make a transient instance persistent. As the syntax suggests it does not return any value.

Let’s see the below code snippet to persist a transient object into the database.

import java.util.Date;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.hibernate.entity.Orders;
import com.hibernate.util.HibernateUtil;

public class SessionInterfaceMethods {

	public static void main(String[] args) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		
		Orders order = new Orders("anndy", new Date(), 500.00);
		
		Transaction t = session.beginTransaction();
		
		session.persist(order);
		
		t.commit();
		session.close();
		
	}
}

when you run the above code it will insert a record into the database.

Hibernate: insert into orders (orderAmount, orderBy, orderDate) values (?, ?, ?)

load():

Syntax:

public Object load(Class theClass, Serializable id);

Return the persistent instance of the given entity class with the given identifier, assuming that the instance exists. This method might return a proxied instance that is initialized on-demand when a non-identifier method is accessed. As stated it is used to retrieve an object that you assume exists in the database if the object with the given identifier is not found it will throw “org.hibernate.ObjectNotFoundException”. So this method should not be used to determine whether an object exists or not.

Let’s see the below code snippet to load an object from the database for identifier 2.

import org.hibernate.Session;

import com.hibernate.entity.Orders;
import com.hibernate.util.HibernateUtil;

public class SessionInterfaceMethods {

	public static void main(String[] args) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		
		Orders order = (Orders) session.load(Orders.class, 2);
		System.out.println(order);
		session.close();	
	}
}

When we run this code it will execute a select query and return an object of Orders if it exists or it will throw an Exception mention above.

Hibernate: select orders0_.orderNo as orderNo1_1_0_, orders0_.orderAmount as orderAmo2_1_0_, orders0_.orderBy as orderBy3_1_0_, orders0_.orderDate as orderDat4_1_0_ from orders orders0_ where orders0_.orderNo=?
Orders [orderNo=2, orderBy=kamal, orderDate=2018-11-10 13:51:31.0, orderAmount=1100.5]

get():

Syntax:

public Object get(Class clazz, Serializable id);

Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance. (If the instance is already associated with the session, return that instance. This method never returns an uninitialized instance.)

Let’s see the below code snippet to get an object from the database for identifier 1.

import org.hibernate.Session;

import com.hibernate.entity.Orders;
import com.hibernate.util.HibernateUtil;

public class SessionInterfaceMethods {

	public static void main(String[] args) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		
		Orders order = (Orders) session.get(Orders.class, 1);
		System.out.println(order);
		session.close();
		
	}
}

When we run this code it will execute a select query and return an object of Orders if it exists or null.

Hibernate: select orders0_.orderNo as orderNo1_1_0_, orders0_.orderAmount as orderAmo2_1_0_, orders0_.orderBy as orderBy3_1_0_, orders0_.orderDate as orderDat4_1_0_ from orders orders0_ where orders0_.orderNo=?
Orders [orderNo=1, orderBy=Ram, orderDate=2018-11-10 13:44:10.0, orderAmount=1000.5]

update():

Syntax:

public void update(Object object);

Update the persistent instance with the identifier of the given detached instance. If there is a persistent instance with the same identifier, an exception is thrown.

Let’s examine the below code snippet.

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

import com.hibernate.entity.Orders;
import com.hibernate.util.HibernateUtil;

public class SessionInterfaceMethods {

	public static void main(String[] args) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		
		Orders order = (Orders) session.get(Orders.class, 1);
		System.out.println(order);
		
		order.setOrderAmount(2345.00);
		Transaction t = session.beginTransaction();
		session.update(order);
		t.commit();
		System.out.println("order after update :" +order);
		session.close();
	}
}

when you run the above code it will first fetch an object of Orders from the database and then it will execute an update query to update the record with the changes made. See the output of the above code snippet.

Hibernate: select orders0_.orderNo as orderNo1_1_0_, orders0_.orderAmount as orderAmo2_1_0_, orders0_.orderBy as orderBy3_1_0_, orders0_.orderDate as orderDat4_1_0_ from orders orders0_ where orders0_.orderNo=?
Orders [orderNo=1, orderBy=Ram, orderDate=2018-11-10 14:41:33.0, orderAmount=1000.5]
Hibernate: update orders set orderAmount=?, orderBy=?, orderDate=? where orderNo=?
order after update :Orders [orderNo=1, orderBy=Ram, orderDate=2018-11-10 14:41:33.0, orderAmount=2345.0]

saveOrUpdate():

Syntax:

public void saveOrUpdate(Object object);

Either save or update the given instance, depending upon the resolution of the unsaved-value. A transient object will be saved or a detached instance containing a new or updated state will be updated.

Let’s examine the below code snippet.

import java.util.Date;

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

import com.hibernate.entity.Orders;
import com.hibernate.util.HibernateUtil;

public class SessionInterfaceMethods {

	public static void main(String[] args) {
		Session session = HibernateUtil.getSessionFactory().openSession();

		Orders order = new Orders("anna", new Date(), 1540.00);
		Transaction t = session.beginTransaction();
		
		session.saveOrUpdate(order);
		
		t.commit();
		
		System.out.println("order after insert:" +order);
		session.close();
		
		order.setOrderAmount(2000.25);
		session = HibernateUtil.getSessionFactory().openSession();
		t = session.beginTransaction();
		
		session.saveOrUpdate(order);
		
		t.commit();
		session.close();
		System.out.println("order after update :" +order);
	}
}

When you run the above code it will insert a record into the database and later it will update the same instance with a new session. See the below output.

Hibernate: insert into orders (orderAmount, orderBy, orderDate) values (?, ?, ?)
order after insert:Orders [orderNo=5, orderBy=anna, orderDate=Sat Nov 10 14:52:55 IST 2018, orderAmount=1540.0]
Hibernate: update orders set orderAmount=?, orderBy=?, orderDate=? where orderNo=?
order after update :Orders [orderNo=5, orderBy=anna, orderDate=Sat Nov 10 14:52:55 IST 2018, orderAmount=2000.25]

merge():

Syntax:

public Object merge(Object object);

Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session.

Let’s examine the below code snippet.

import java.util.Date;

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

import com.hibernate.entity.Orders;
import com.hibernate.util.HibernateUtil;

public class SessionInterfaceMethods {

	public static void main(String[] args) {
		Session session = HibernateUtil.getSessionFactory().openSession();

		Orders order = new Orders("tina", new Date(), 1999.00);
		
		Transaction t = session.beginTransaction();
		
		session.save(order);
		
		t.commit();
		
		System.out.println("order after insert:" +order);
		session.evict(order);
		
		order.setOrderAmount(2999.00);
		t = session.beginTransaction();
		order = (Orders) session.merge(order);
		t.commit();
		session.close();
		System.out.println("order after merge :" +order);
	}
}

When you run the above code it will insert the order object. As we have called the evict method of the session, now if we call the merge method it will first load the persistent object from the database and then it will be updated. See the output of the above code snippet.

Hibernate: insert into orders (orderAmount, orderBy, orderDate) values (?, ?, ?)
order after insert:Orders [orderNo=7, orderBy=tina, orderDate=Sat Nov 10 15:20:32 IST 2018, orderAmount=1999.0]
Hibernate: select orders0_.orderNo as orderNo1_1_0_, orders0_.orderAmount as orderAmo2_1_0_, orders0_.orderBy as orderBy3_1_0_, orders0_.orderDate as orderDat4_1_0_ from orders orders0_ where orders0_.orderNo=?
Hibernate: update orders set orderAmount=?, orderBy=?, orderDate=? where orderNo=?
order after merge :Orders [orderNo=7, orderBy=tina, orderDate=Sat Nov 10 15:20:32 IST 2018, orderAmount=2999.0]

delete():

Syntax:

public void delete(Object object);

Remove a persistent instance from the database. The argument may be an instance associated with the receiving Session or a transient instance with an identifier associated with an existing persistent state.

Let’s examine the below code snippet.

import java.util.Date;

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

import com.hibernate.entity.Orders;
import com.hibernate.util.HibernateUtil;

public class SessionInterfaceMethods {

	public static void main(String[] args) {
		Session session = HibernateUtil.getSessionFactory().openSession();

		Orders order = new Orders("tina", new Date(), 1999.00);
		
		order.setOrderNo(7); // assigning an existing order no this transient instance. 
		
		Transaction t = session.beginTransaction();
		
		session.delete(order);
		
		t.commit();
		
	}
}

When you run the above code it will delete the record having ID as 7 from the database. See the output of the above code snippet.

Hibernate: delete from orders where orderNo=?

refresh():

Syntax:

public void refresh(Object object);

Re-read the state of the given instance from the underlying database.

Let’s examine the below code snippet.

import org.hibernate.Session;

import com.hibernate.entity.Orders;
import com.hibernate.util.HibernateUtil;

public class SessionInterfaceMethods {

	public static void main(String[] args) {
		Session session = HibernateUtil.getSessionFactory().openSession();

		Orders order = new Orders("bill", new Date(), 590.00);
		System.out.println("intial order transient instance "+order);
		
		session.save(order);
		
		session.flush();
		
		session.refresh(order);
		System.out.println("order loaded from the database after refresh "+order);
		
	}	
}

When you run the above code it will fire an insert query on a transient object having any ID as null. When calling the refresh method on the same object we will get the ID. See the output of the above code snippet.

intial order transient instance Orders [orderNo=null, orderBy=bill, orderDate=Sat Nov 10 15:44:52 IST 2018, orderAmount=590.0]
Hibernate: insert into orders (orderAmount, orderBy, orderDate) values (?, ?, ?)
Hibernate: select orders0_.orderNo as orderNo1_1_0_, orders0_.orderAmount as orderAmo2_1_0_, orders0_.orderBy as orderBy3_1_0_, orders0_.orderDate as orderDat4_1_0_ from orders orders0_ where orders0_.orderNo=?
order loaded from the database after refresh Orders [orderNo=9, orderBy=bill, orderDate=2018-11-10 15:44:52.0, orderAmount=590.0]

flush():

Syntax:

public void flush() throws HibernateException;

Force this session to flush. Must be called at the end of a unit of work, before committing the transaction and closing the session. Flushing is the process of synchronizing the underlying persistent store with a persistent state held in memory.

Let’s examine the below code snippet.

import java.util.Date;


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

import com.hibernate.entity.Orders;
import com.hibernate.util.HibernateUtil;

public class SessionInterfaceMethods {

	public static void main(String[] args) {
		Session session = HibernateUtil.getSessionFactory().openSession();

		Orders order = new Orders("bill", new Date(), 590.00);
		System.out.println("intial order transient instance "+order);
		
		Transaction t = session.beginTransaction();
		
		session.save(order);
		
		session.flush();
		
		t.commit();
		
		session.close();
	}	
	
}

When you run the above code it will fire insert query when we call session.flush(). At this stage, the persistent object is synced with the database but the object is still to be persisted. The object will only persist when we commit the transaction. This method is useful when we require the ID of a persisting object before it is persisted into the database.

close():

Syntax:

public Connection close() throws HibernateException;

End the session by releasing the JDBC connection and cleaning up. It is not strictly necessary to close the session but you must at least disconnect it.

See the use of the close method in the above-used code snippet.

clear():
Syntax:

public void clear();

Completely clear the session. Evict all loaded instances and cancel all pending saves, updates, and deletions. Do not close open iterators or instances of ScrollableResults.

To use it just called session.clear();

session.clear();

cancelQuery():

Syntax:

public void cancelQuery() throws HibernateException;

Cancel the execution of the current query. This is the sole method of the session which may be safely called from another thread. throws HibernateException if there was a problem canceling the query.

evict():
Syntax:

public void evict(Object object);

Remove this instance from the session cache. Changes to the instance will not be synchronized with the database.

Let’s examine the below code snippet.

import java.util.Date;

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

import com.hibernate.entity.Orders;
import com.hibernate.util.HibernateUtil;

public class SessionInterfaceMethods {

	public static void main(String[] args) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		
		Orders order  = new Orders("lisa", new Date(), 2349.90);
		Transaction t = session.beginTransaction();
		session.save(order);
		t.commit();
		System.out.println("order after save is "+order);
		
		session.evict(order);
		System.out.println("order after sesion evict "+order);
		
		t = session.beginTransaction();
		session.save(order);
		t.commit();
		session.close();
	}	
}

When you run the above code it will persist an instance of Orders into the database. Once we call the session.evict() the instance of orders will we be considered as a new instance of orders if we call session.save() on it. See the output of the above code snippet.

Hibernate: insert into orders (orderAmount, orderBy, orderDate) values (?, ?, ?)
order after save is Orders [orderNo=12, orderBy=lisa, orderDate=Sat Nov 10 16:15:43 IST 2018, orderAmount=2349.9]
order after sesion evict Orders [orderNo=12, orderBy=lisa, orderDate=Sat Nov 10 16:15:43 IST 2018, orderAmount=2349.9]
Hibernate: insert into orders (orderAmount, orderBy, orderDate) values (?, ?, ?)

doWork():

Syntax:

public void doWork(Work work) throws HibernateException;

Controller for allowing users to perform JDBC related work using the Connection managed by this Session. As the syntax suggests return type as void it will not return any value. to return value use doReturningWork().

Let’s examine the below code snippet.

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Date;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.jdbc.Work;

import com.hibernate.util.HibernateUtil;

public class SessionInterfaceMethods {

	public static void main(String[] args) {
		
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction t = session.beginTransaction();
		session.doWork(new Work() {
			String query = "insert into orders (orderAmount, orderBy, orderDate) values (?, ?, ?)";	
			public void execute(Connection connection) throws SQLException {
				PreparedStatement ps = connection.prepareStatement(query);
				ps.setDouble(1, 3999.99);
				ps.setString(2, "addy");
				ps.setTimestamp(3, new Timestamp(new Date().getTime()));
				
				int result = ps.executeUpdate();
				System.out.println("result is "+result);
			}
		});
		t.commit();
		session.close();
	}	
}

When you run the above code it will insert a new record into the database with the given values.

result is 1

doReturningWork():

Syntax:

public  T doReturningWork(ReturningWork work) throws HibernateException;

Controller for allowing users to perform JDBC related work using the Connection managed by this Session. After execution returns the result.

Let’s examine the below code snippet.

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.jdbc.ReturningWork;
import com.hibernate.util.HibernateUtil;

public class SessionInterfaceMethods {

	public static void main(String[] args) {
		
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction t = session.beginTransaction();
		
		session.doReturningWork(new ReturningWork<Double>() {

			public Double execute(Connection connection) throws SQLException {
				PreparedStatement ps = connection.prepareStatement("select orderAmount from orders where orderNo = 6");
				ResultSet rs = ps.executeQuery();
				rs.next();
				Double orderAmount = rs.getDouble("orderAmount");
				System.out.println("orderAmount "+orderAmount);
				return orderAmount;
			}
			
		});
		t.commit();
		session.close();
	}	
}

When you run the above code it will print the output

orderAmount 1780.0

This is very useful when we have to call a stored procedure that returns some values.

That’s it in commonly used methods of session interface.

Read more about hibernate.

Reference https://docs.jboss.org/hibernate/orm/3.5/javadocs/org/hibernate/Session.html

HAPPY LEARNING !!

Hibernate CRUD operations with example

In computer programming, create, read, update and delete commonly known as (CRUD) are the four basic functions of persistent storage.

Let’s write an example to achieve CRUD operation using Hibernate.

The requirement for this project:

  • MySQL 5.1.6
  • Java 8 (JDK 1.8)
  • Hibernate 4.3.5

To perform CRUD operation we will require a table in the database. So first create a table “Product“.

CREATE  TABLE `Product` (

  `product_id` INT NOT NULL AUTO_INCREMENT ,

  `product_name` VARCHAR(200) NULL ,

  `company_name` VARCHAR(100) NULL ,

  PRIMARY KEY (`product_id`) 
 );
 

Once the database table is created successfully, create a maven project in eclipse. After the creation of the project, the project structure will be as below.
Hibernate CRUD operations

Once the project created successfully open the “pom.xml” file and add the following dependencies. This file is used to add all the required dependency to the project.

<dependency>
  		<groupId>org.hibernate</groupId>
  		<artifactId>hibernate-core</artifactId>
  		<version>4.3.5.Final</version>
  	</dependency>
  	<dependency>
  		<groupId>mysql</groupId>
  		<artifactId>mysql-connector-java</artifactId>
  		<version>5.1.6</version>
  	</dependency>

The complete pom.xml file.

<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>hibernate4</groupId>
  <artifactId>hibernate</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>hibernate</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>
    <dependency>
  		<groupId>org.hibernate</groupId>
  		<artifactId>hibernate-core</artifactId>
  		<version>4.3.5.Final</version>
  	</dependency>
  	<dependency>
  		<groupId>mysql</groupId>
  		<artifactId>mysql-connector-java</artifactId>
  		<version>5.1.6</version>
  	</dependency>
  </dependencies>
</project>

Now create a XML file as “hibernate.cfg.xml” under src/main/resources. As the name suggests this file is used to define all the configurations related to the database and mapping class.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
		"http://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost/hibernate_dev</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">root</property>
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<property name="hibernate.show_sql">true</property>
		<property name="hbm2ddl.auto">update</property>
	</session-factory>
</hibernate-configuration>

* Make sure you update database details like port, database schema, user name, and password according to your database configuration in the “hibernate.cfg.xml” file.

We are all set with hibernate configuration. The next step is to create a utility class to define and build a SessionFactory object. To read about Session factory click here

Create a class “HibernateUtil.java” under src/main/java.

package com.hibernate.util;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {

	private static SessionFactory sessionFactory = null;

	private static SessionFactory buildSessionFactory() {
		try {
			Configuration configuration = new Configuration();
			configuration.configure("hibernate.cfg.xml");

			ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
					.applySettings(configuration.getProperties()).build();
			SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
			System.out.println("Session factory created successfully");
			return sessionFactory;
		} catch (Throwable ex) {
			System.err.println("SessionFactory creation failed." + ex);
			ex.printStackTrace();
			throw new ExceptionInInitializerError(ex);
		}
	}

	public static SessionFactory getSessionFactory() {
		if (sessionFactory == null)
			sessionFactory = buildSessionFactory();
		return sessionFactory;
	}
}

Create a class “ProductEntity.java” which is the object representation of the Product table.

package com.hibernate.entity;
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;

@Entity
@Table(name="Product")
public class ProductEntity implements  Serializable{

	private static final long serialVersionUID = 8867565466924455293L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="product_id")
	private Integer productId;
	
	@Column(name="product_name")
	private String productName;
	
	@Column(name="company_name")
	private String companyName;

	public Integer getProductId() {
		return productId;
	}

	public void setProductId(Integer productId) {
		this.productId = productId;
	}

	public String getProductName() {
		return productName;
	}

	public void setProductName(String productName) {
		this.productName = productName;
	}

	public String getCompanyName() {
		return companyName;
	}

	public void setCompanyName(String companyName) {
		this.companyName = companyName;
	}

	@Override
	public String toString() {
		return "ProductEntity [productId=" + productId + ", productName=" + productName + ", companyName=" + companyName
				+ "]";
	}
}

To map the Entity with the database, the entity class needs to map in the “Hibernate.cfg.xml” file.
Add below line in “Hibernate.cfg.xml” file before


<mapping class="com.hibernate.entity.ProductEntity"/>

Now we are all set to test the CURD operation let’s write an example class to test.

Create a class “CurdOperationExample.java”

package com.hibernate.curd;

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

import com.hibernate.entity.ProductEntity;
import com.hibernate.util.HibernateUtil;

public class CurdOperationExample {

	public ProductEntity saveProduct(ProductEntity product) {
		Transaction t = null;
		Session session = null;
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			t = session.beginTransaction();
			Integer id = (Integer) session.save(product);
			product.setProductId(id);
			t.commit();

		} catch (Exception e) {
			e.printStackTrace();
			t.rollback();
		} finally {
			if (session != null)
				session.close();
		}
		return product;
	}

	public void updateProduct(ProductEntity product) {
		Transaction t = null;
		Session session = null;
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			t = session.beginTransaction();
			session.update(product);
			t.commit();

		} catch (Exception e) {
			e.printStackTrace();
			t.rollback();
		} finally {
			if (session != null)
				session.close();
		}
	}

	public void deleteProduct(ProductEntity product) {
		Transaction t = null;
		Session session = null;
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			t = session.beginTransaction();
			session.delete(product);
			t.commit();
			System.out.println("product deleted successfully");
		} catch (Exception e) {
			e.printStackTrace();
			t.rollback();
		} finally {
			if (session != null)
				session.close();
		}
	}

	public ProductEntity fetchroduct(Integer ProductId) {
		Session session = null;
		ProductEntity entity =  null;
		try {
			session = HibernateUtil.getSessionFactory().openSession();
			entity = (ProductEntity) session.get(ProductEntity.class, ProductId);
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (session != null)
				session.close();
		}
		return entity;
	}

	public static void main(String[] args) {
		ProductEntity product = new ProductEntity();
		product.setProductName("test product");
		product.setCompanyName("test company");
		
		CurdOperationExample example = new CurdOperationExample();
		
		System.out.println("before saving product is "+product);
		
		example.saveProduct(product);
		
		System.out.println("after saving product is "+product);
		
		System.out.println("modifing product name before update "+product);
		product.setProductName("new test product"); // set new product name
		example.updateProduct(product);
		System.out.println("after updating product is "+product);	
		
		ProductEntity newProduct = example.fetchroduct(1);
		
		System.out.println("product fetch is "+ newProduct);
		
		System.out.println("deleting product");
		example.deleteProduct(newProduct);
		
		System.out.println("after delete fetch product");
		
		newProduct = example.fetchroduct(1);
		
		System.out.println("after product deleted product is "+ newProduct);
		
	}
}

Run this class as a java program and it will produce below output.

before saving product is ProductEntity [productId=null, productName=test product, companyName=test company]
Sep 09, 2018 11:38:11 AM org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {4.0.4.Final}
Sep 09, 2018 11:38:11 AM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.3.5.Final}
Sep 09, 2018 11:38:11 AM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
Sep 09, 2018 11:38:11 AM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
Sep 09, 2018 11:38:11 AM org.hibernate.cfg.Configuration configure
INFO: HHH000043: Configuring from resource: hibernate.cfg.xml
Sep 09, 2018 11:38:11 AM org.hibernate.cfg.Configuration getConfigurationInputStream
INFO: HHH000040: Configuration resource: hibernate.cfg.xml
Sep 09, 2018 11:38:12 AM org.hibernate.cfg.Configuration doConfigure
INFO: HHH000041: Configured SessionFactory: null
Sep 09, 2018 11:38:12 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH000402: Using Hibernate built-in connection pool (not for production use!)
Sep 09, 2018 11:38:12 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000401: using driver [com.mysql.jdbc.Driver] at URL [jdbc:mysql://localhost/hibernate_dev]
Sep 09, 2018 11:38:12 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000046: Connection properties: {user=root, password=****}
Sep 09, 2018 11:38:12 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH000006: Autocommit mode: false
Sep 09, 2018 11:38:12 AM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
Sep 09, 2018 11:38:13 AM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
Sep 09, 2018 11:38:13 AM org.hibernate.engine.jdbc.internal.LobCreatorBuilder useContextualLobCreation
INFO: HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4
Sep 09, 2018 11:38:13 AM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000399: Using default transaction strategy (direct JDBC transactions)
Sep 09, 2018 11:38:13 AM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397: Using ASTQueryTranslatorFactory
Sep 09, 2018 11:38:13 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000228: Running hbm2ddl schema update
Sep 09, 2018 11:38:13 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000102: Fetching database metadata
Sep 09, 2018 11:38:13 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000396: Updating schema
Sep 09, 2018 11:38:14 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000261: Table found: hibernate_dev.product
Sep 09, 2018 11:38:14 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000037: Columns: [product_id, company_name, product_name]
Sep 09, 2018 11:38:14 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000108: Foreign keys: []
Sep 09, 2018 11:38:14 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000126: Indexes: [primary]
Sep 09, 2018 11:38:14 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000261: Table found: hibernate_dev.user_data
Sep 09, 2018 11:38:14 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000037: Columns: [password, user_id_pk, user_name, mobile, email]
Sep 09, 2018 11:38:14 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000108: Foreign keys: []
Sep 09, 2018 11:38:14 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000126: Indexes: [primary]
Sep 09, 2018 11:38:14 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000232: Schema update complete

Hibernate: insert into Product (company_name, product_name) values (?, ?)
after saving product is ProductEntity [productId=1, productName=test product, companyName=test company]
modifing product name before update ProductEntity [productId=1, productName=test product, companyName=test company]
Hibernate: update Product set company_name=?, product_name=? where product_id=?
after updating product is ProductEntity [productId=1, productName=new test product, companyName=test company]
Hibernate: select productent0_.product_id as product_1_0_0_, productent0_.company_name as company_2_0_0_, productent0_.product_name as product_3_0_0_ from Product productent0_ where productent0_.product_id=?
product fetch is ProductEntity [productId=1, productName=new test product, companyName=test company]
deleting product
Hibernate: delete from Product where product_id=?
product deleted successfully
after delete fetch product
Hibernate: select productent0_.product_id as product_1_0_0_, productent0_.company_name as company_2_0_0_, productent0_.product_name as product_3_0_0_ from Product productent0_ where productent0_.product_id=?
after product deleted product is null

Read hibernate in more detail.

Happy Learning !!

Steps to configure Hibernate using maven

In this post, we will discuss how we can configure the hibernate project using maven.

Create a Maven project in Eclipse gives it any name of your choice. After the creation of the project, the project structure will look like as below.

Steps to configure Hibernate using maven

The requirements for this project is:

  • MySQL 5.1.6
  • Java 8 (JDK 1.8)
  • Hibernate 4.3.5

Once the project created successfully open the “pom.xml” file and add the following dependencies. This file is used to add all the required dependency to the project. You can download these dependencies from the maven repository as well.

<dependency>
  		<groupId>org.hibernate</groupId>
  		<artifactId>hibernate-core</artifactId>
  		<version>4.3.5.Final</version>
  	</dependency>
  	<dependency>
  		<groupId>mysql</groupId>
  		<artifactId>mysql-connector-java</artifactId>
  		<version>5.1.6</version>
  	</dependency>

The complete pom.xml file.

<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>hibernate4</groupId>
  <artifactId>hibernate</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>hibernate</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>
    <dependency>
  		<groupId>org.hibernate</groupId>
  		<artifactId>hibernate-core</artifactId>
  		<version>4.3.5.Final</version>
  	</dependency>
  	<dependency>
  		<groupId>mysql</groupId>
  		<artifactId>mysql-connector-java</artifactId>
  		<version>5.1.6</version>
  	</dependency>
  </dependencies>
</project>

Now create a XML file as “hibernate.cfg.xml” under src/main/resources. As the name suggests this file is used to define all the configurations related to the database and mapping class.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
		"http://hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost/hibernate_dev</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">root</property>
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<property name="hibernate.show_sql">true</property>
		<property name="hbm2ddl.auto">update</property>
	</session-factory>
</hibernate-configuration>

We are all set with hibernate configuration. The next step is to create a utility class to define and build a SessionFactory object. You can read more on Session factory Here

Create a class “HibernateUtil.java” under src/main/java.

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {

	private static SessionFactory sessionFactory = null;

	private static SessionFactory buildSessionFactory() {
		try {
			Configuration configuration = new Configuration();
			configuration.configure("hibernate.cfg.xml");
			System.out.println("Hibernate Configuration loaded");

			ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
					.applySettings(configuration.getProperties()).build();
			SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry);
			System.out.println("Session factory created successfully");
			return sessionFactory;
		} catch (Throwable ex) {
			System.err.println("SessionFactory creation failed." + ex);
			ex.printStackTrace();
			throw new ExceptionInInitializerError(ex);
		}
	}

	public static SessionFactory getSessionFactory() {
		if (sessionFactory == null)
			sessionFactory = buildSessionFactory();
		return sessionFactory;
	}
}

Now, let’s verify the configuration we have made. First, we have to create a table in the database.

Create Table “user_data“.

CREATE  TABLE `hibernate_dev`.`user_data` (

  `user_id_pk` INT NOT NULL AUTO_INCREMENT ,

  `user_name` VARCHAR(45) NULL ,

  `email` VARCHAR(45) NULL ,

  `password` VARCHAR(45) NULL ,

  `mobile` VARCHAR(10) NULL ,

  PRIMARY KEY (`user_id_pk`) );

Create a class “UserDataEntity.java” which is the object representation of the user_data table.

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;

@Entity
@Table(name="user_id")
public class UserDataEntity implements Serializable{

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="user_id_pk")
	private Integer userIdPk;
	
	@Column(name="user_name")
	private String user_name;
	
	@Column(name="email")
	private String email;
	
	@Column(name="password")
	private String passowrd;
	
	@Column(name="mobile")
	private String mobile;

	public Integer getUserIdPk() {
		return userIdPk;
	}

	public void setUserIdPk(Integer userIdPk) {
		this.userIdPk = userIdPk;
	}

	public String getUser_name() {
		return user_name;
	}

	public void setUser_name(String user_name) {
		this.user_name = user_name;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getPassowrd() {
		return passowrd;
	}

	public void setPassowrd(String passowrd) {
		this.passowrd = passowrd;
	}

	public String getMobile() {
		return mobile;
	}

	public void setMobile(String mobile) {
		this.mobile = mobile;
	}
	
}

Add below line in “Hibernate.cfg.xml” before

<mapping class="com.hibernate.entity.UserDataEntity"/>

Let run a test to save user data into the database. create a class to run the test as below.

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

import com.hibernate.entity.UserDataEntity;
import com.hibernate.util.HibernateUtil;

public class HibernateApp {

	public static void main(String[] args) {
		UserDataEntity entity = new UserDataEntity();
		entity.setEmail("testuser@gmail.com");
		entity.setMobile("9000123456");
		entity.setPassowrd("TestUser123");
		entity.setUserName("TESTUSER");
		try{
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction t = session.beginTransaction();
		session.save(entity);
		t.commit();
		session.close();
		}catch (Exception e) {
			e.printStackTrace();
		}
	}
}

The output will of the program

Hibernate: insert into user_data (email, mobile, password, user_name) values (?, ?, ?, ?)

Check in the database table, the record will be as below.

db output

Recommended Read

Commonly used methods of org.hibernate.Session Interface.
Hibernate CRUD operations
The N+1 Query Problem example with hibernate

Happy Learning !!