hibernate

Hibernate JNDI Example

A database connection is expensive to make, yet all web applications use it. That is why most of the servlet containers provide built-in support for connection pooling. We can leverage this connection pooling in any webserver by registering the datasource via the JNDI context. In this tutorial, we will explain how to configure a datasource in Tomcat and how to obtain an instance of this datasource via JNDI.
 
 
 
 
 
 

1. Introduction

Using Hibernate framework in a web application is very easy, all we need is to configure datasource properties in hibernate configuration file. But before we move on, let’s take a look and understand the Hibernate framework and JNDI.

1.1 What is Hibernate?

  • Hibernate is the Opensource lightweight ORM (Object Relational Mapping) based framework to communicate with a database. ORM is a programming technique that maps the object to the data stored in the database.
  • Hibernate framework makes the development of Java application to interact with the database in a simple manner.
  • Hibernate handles mapping of Java classes to database tables (i.e. Java data types and SQL data types).
  • Hibernate also provides data query and retrieval facilities.
  • Hibernate is purely used for data persistence (i.e. to store/retrieve data from the database).
  • Hibernate framework internally uses the JDBC API to interact with the database. It hides internal JDBC implementations from end users.

1.2 Hibernate Architecture

There are 4 layers in Hibernate architecture i.e. Java Application Layer, Hibernate Framework Layer, Backhand API Layer and Database Layer. Let’s understand the diagram of hibernate architecture:

Fig. 1: Hibernate Architecture
Fig. 1: Hibernate Architecture

For creating the first Hibernate application, we must know the elements of Hibernate architecture. They are as follows:

ElementDescription
SessionFactoryThe SessionFactory is a factory of session and client of Connection Provider. It holds second level cache (optional) of data.
SessionThe session object provides an interface between the application and data stored in the database. It is a short-lived object and wraps the JDBC connection. It is a factory of Transaction, Query, and Criteria and holds a first-level cache (mandatory) of data. The Session interface provides methods to INSERT, UPDATE and DELETE the object.
TransactionThe transaction object specifies the atomic unit of work and is an optional parameter in Hibernate framework.
ConnectionProviderIt is a factory of JDBC connections and abstracts the application from Driver Manager or DataSource. It is an optional parameter in Hibernate framework.
TransactionFactoryIt is a factory of Transaction and is again an optional parameter in Hibernate framework.

1.3 Hibernate Benefits

There are many advantages of using the hibernate framework, for e.g.

  • Takes care of mapping Java classes to database tables using XML files and without writing any line of code.
  • Provides simple APIs for storing and retrieving Java objects directly to and from the database.
  • Provides the facility to create the tables of the database automatically. So, there is no need to create tables in the database manually.
  • If there is a change in a database or in any table then the only need to change XML file properties.
  • Minimize database access with smart fetching strategies as Hibernate framework internally uses the cache technique.
  • Provides simple querying of data.

1.4 What is JNDI?

  • JNDI stands for Java Naming and Directory Interface.
  • It’s a Java API for a directory service that allows Java clients to discover and look up data and objects via a name.
  • It’s just an interface and hence it is independent of the underlying implementation.
  • In simple words, JNDI provides a mechanism to bind an object to a name.

1.5 Why we need to use JNDI?

JNDI allows distributed applications to look up services in a resource-independent way.

Since it is independent of any specific naming or directory service implementation, it enables applications to access different naming and directory services like DNS, LDAP, CORBA and RMI using a common API.

1.6 When to use JNDI?

The most common use case is to set up a database connection pool on a Java EE application server.

Any application that is deployed on such server (where JNDI is configured) can gain access to the connections they need using the JNDI name without having any knowledge about the connection and the underlying database.

For E.g.:

java:comp/env/testDatabasePool

1.7 Download and Install Hibernate

You can read this tutorial in order to download and install Hibernate in the Eclipse IDE.

1.8 Download and Install MySQL

You can watch this video in order to download and install the MySQL database on your windows operations system.

Now, open up the Eclipse IDE and let’s start building the application!

2. Hibernate JNDI Example

2.1 Tools Used

We are using Eclipse Kepler SR2, JDK 8 (1.8.0_131), Tomcat7 application server, MySQL database, and Maven (to download the MySQL connector jar and Hibernate libraries). Having said that, we have tested the code against JDK 1.7 and it works well.

2.2 Project Structure

Firstly, let’s review the final project structure, in case you are confused about where you should create the corresponding files or folder later!

Fig. 2: Hibernate JNDI Application Project Structure
Fig. 2: Hibernate JNDI Application Project Structure

Tip
You may skip project creation and jump directly to the beginning of the example below.

2.3 Project Creation

This section will demonstrate on how to create a Dynamic Web Java Maven project with Eclipse. In Eclipse IDE, go to File -> New -> Maven Project

Fig. 3: Create Maven Project
Fig. 3: Create Maven Project

In the New Maven Project window, it will ask you to select project location. By default, ‘Use default workspace location‘ will be selected. Just click on Next button to proceed without making any changes.

Fig. 4: Project Details
Fig. 4: Project Details

In the next screen, it will ask you to select an archetype. Depending on the type of project that you are working, you need to choose the archetype. Select the maven archetype as maven-archetype-webapp and click on next.

Fig. 5: Archetype Selection
Fig. 5: Archetype Selection

It will ask you to ‘Enter a group id for the artifact.’ We will input the details as shown in the below image. The version number will be by default 0.0.1-SNAPSHOT.

Fig. 6: Archetype Parameters
Fig. 6: Archetype Parameters

Click on Finish. The creation of a maven project is completed. If you see, it has downloaded the maven dependencies and a pom.xml file will be created. It will have the following code:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>HibernateJndi</groupId>
   <artifactId>HibernateJndi</artifactId>
   <packaging>war</packaging>
   <version>0.0.1-SNAPSHOT</version>
   <name>HibernateJndi Maven Webapp</name>
   <url>http://maven.apache.org</url>
   <dependencies>
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>3.8.1</version>
         <scope>test</scope>
      </dependency>
   </dependencies>
   <build>
      <finalName>HibernateJndi</finalName>
   </build>
</project>

We can start adding which ever dependencies you want like Hibernate, MySQL, Apache jars etc. By default, it has added JUnit dependency and as said earlier it will add the dependencies based on the archetype we select.

Let’s start building the application!

3. Application Building

Below are the steps involved in developing this application:

3.1 Database & Table Creation

This tutorial uses a database called tutorialdb. The database is not included when you create the project in eclipse so you need to first create the database to follow this tutorial.

  • Create a new database tutorialdb as:
CREATE DATABASE tutorialdb;
  • Use the created database tutorialdb to create table as:
USE tutorialdb;
  • Create the table employee as shown below:
CREATE TABLE employee (id int(11) NOT NULL AUTO_INCREMENT, name varchar(20) DEFAULT NULL, role varchar(20) DEFAULT NULL, insert_time datetime DEFAULT NULL, PRIMARY KEY (id));
  • Insert records in the employee table as shown below:
INSERT INTO employee (id, name, role, insert_time) VALUES (1, 'JavaCodeGeek', 'CEO', now());
INSERT INTO employee (id, name, role, insert_time) VALUES (2, 'Harry Potter', 'Editor', now());
INSERT INTO employee (id, name, role, insert_time) VALUES (3, 'Lucifer', 'Editor', now());

If everything goes well, the table will be shown as below in the MySQL workbench:

Fig. 7: Database and Table Creation
Fig. 7: Database and Table Creation

3.2 Hibernate Maven Dependencies

In this example, we are using Hibernate latest version i.e. hibernate-core-4.3.5.Final and MySQL-connector-java dependency.

A quick note, even if we don’t add MySQL driver dependency, the project will compile and run fine. However, it’s better to include it so that if someone will look at the project dependencies, it will be clear for him/her to understand that we are using MySQL database.

The updated file will have the following code:

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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>HibernateJndi</groupId>
   <artifactId>HibernateJndi</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>war</packaging>
   <dependencies>
      <dependency>
         <groupId>org.hibernate</groupId>
         <artifactId>hibernate-core</artifactId>
         <version>4.3.5.Final</version>
      </dependency>
      <dependency>
         <groupId>javax.servlet</groupId>
         <artifactId>javax.servlet-api</artifactId>
         <version>3.0.1</version>
         <scope>provided</scope>
      </dependency>
      <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-simple</artifactId>
         <version>1.7.5</version>
      </dependency>
      <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
         <version>5.0.5</version>
         <scope>provided</scope>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <plugin>
            <artifactId>maven-war-plugin</artifactId>
            <version>2.3</version>
            <configuration>
               <warSourceDirectory>WebContent</warSourceDirectory>
               <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
         </plugin>
         <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
               <source>1.7</source>
               <target>1.7</target>
            </configuration>
         </plugin>
      </plugins>
      <finalName>${project.artifactId}</finalName>
   </build>
</project>

3.3 Java Class Creation

Let’s create the required java files. Right click on src folder New -> Package

Fig. 8: Java Package Creation
Fig. 8: Java Package Creation

A new pop window will open where we will enter the package name as com.jcg.hibernate.jndi.model

Fig. 9: Java Package Name (com.jcg.hibernate.jndi.model)
Fig. 9: Java Package Name (com.jcg.hibernate.jndi.model)

Repeat the above step (i.e. Fig. 8) and enter the package name com.jcg.hibernate.jndi.listener

Fig. 10: Java Package Name (com.jcg.hibernate.jndi.listener)
Fig. 10: Java Package Name (com.jcg.hibernate.jndi.listener)

Again, repeat the step listed in Fig. 8 and enter the package name com.jcg.hibernate.jndi

Fig. 11: Java Package Name (com.jcg.hibernate.jndi)
Fig. 11: Java Package Name (com.jcg.hibernate.jndi)

Once the packages are created in the application, we will need to create the required model, session factory listener and servlet implementation class. Right click on the newly created package New -> Class

Fig. 12: Java Class Creation
Fig. 12: Java Class Creation

A new pop window will open and enter the file name as Employee. The model class will be created inside the package: com.jcg.hibernate.jndi.model

Fig. 13: Java Class (Employee.java)
Fig. 13: Java Class (Employee.java)

Repeat the step (i.e. Fig. 12) and enter the filename as HibernateSessionFactoryListener. The listener class will be created inside the package: com.jcg.hibernate.jndi.listener

Fig. 14: Java Class (HibernateSessionFactoryListener.java)
Fig. 14: Java Class (HibernateSessionFactoryListener.java)

Again, repeat the step listed in Fig. 12 and enter the file name as GetEmployeeById. The servlet implementation class will be created inside the package – com.jcg.hibernate.jndi

Fig. 15: Java Class (GetEmployeeById.java)
Fig. 15: Java Class (GetEmployeeById.java)

3.3.1 Implementation of Model Class

In this class, we are using annotations to map the objects to the defined employee table. Add the following code to it:

Employee.java

package com.jcg.hibernate.jndi.model;

import java.util.Date;

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

@Entity
@Table(name="employee", uniqueConstraints={@UniqueConstraint(columnNames={"id"})})
public class Employee {

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="id", nullable=false, unique=true, length=11)
	private int empId;

	@Column(name="name", length=20, nullable=true)
	private String empName;

	@Column(name="role", length=20, nullable=true)
	private String empRole;

	@Column(name="insert_time", nullable=true)
	private Date createdDate;

	public int getEmpId() {
		return empId;
	}

	public void setEmpId(int empId) {
		this.empId = empId;
	}

	public String getEmpName() {
		return empName;
	}

	public void setEmpName(String empName) {
		this.empName = empName;
	}

	public String getEmpRole() {
		return empRole;
	}

	public void setEmpRole(String empRole) {
		this.empRole = empRole;
	}

	public Date getCreatedDate() {
		return createdDate;
	}

	public void setCreatedDate(Date createdDate) {
		this.createdDate = createdDate;
	}
}

3.3.2 Implementation of Servlet Listener Class

This class helps in creating the SessionFactory from the Hibernate configuration file. The SessionFactory is threadsafe, so it is not necessary to obtain one for each thread. Add the following code to it:

HibernateSessionFactoryListener.java

package com.jcg.hibernate.jndi.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

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

@WebListener
public class HibernateSessionFactoryListener implements ServletContextListener {

	public final Logger logger = Logger.getLogger(HibernateSessionFactoryListener.class);
	public void contextDestroyed(ServletContextEvent servletContextEvent) {
		SessionFactory sessionFactoryObj = (SessionFactory) servletContextEvent.getServletContext().getAttribute("SessionFactory");
		if(sessionFactoryObj != null && !sessionFactoryObj.isClosed()) {
			logger.info("Closing Session Factory Object!");
			sessionFactoryObj.close();
		}
		logger.info("Hibernate Session Factory Object Released!");
	}

	public void contextInitialized(ServletContextEvent servletContextEvent) {
		// Creating Configuration Instance & Passing Hibernate Configuration File
		Configuration configObj = new Configuration();
		configObj.configure("hibernate.cfg.xml");

		// Since Hibernate Version 4.x, Service Registry Is Being Used
		ServiceRegistry serviceRegistryObj = new StandardServiceRegistryBuilder().applySettings(configObj.getProperties()).build(); 

		// Creating Hibernate Session Factory Instance
		SessionFactory factoryObj = configObj.buildSessionFactory(serviceRegistryObj);

		// Saving Hibernate Session Factory Object In The Request Scope
		servletContextEvent.getServletContext().setAttribute("SessionFactory", factoryObj);
		logger.info("Hibernate Session Factory Configured Successfully!");
	}
}

3.3.3 Implementation of Servlet Class

This class is a simple servlet where we will pass employee id as a requested parameter and will print out the employee information from the database. In this, we are using @WebServlet annotation to provide the URI pattern for it. Add the following code to it:

GetEmployeeById.java

package com.jcg.hibernate.jndi;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.jboss.logging.Logger;

import com.jcg.hibernate.jndi.model.Employee;

@WebServlet("/GetEmployeeById")
public class GetEmployeeById extends HttpServlet {
	
	private static Employee employeeObj;	
	private static final long serialVersionUID = 1L;
	public final Logger logger = Logger.getLogger(GetEmployeeById.class);

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		int employeeId = Integer.parseInt(request.getParameter("empId"));
		logger.info("Selected Employee Id?= "+ employeeId);

		SessionFactory sessionFactoryObj = (SessionFactory) request.getServletContext().getAttribute("SessionFactory");

		// Get Current Session For Performing The Transaction Queries
		Session sessionObj = sessionFactoryObj.getCurrentSession();

		// Begin Transaction
		Transaction transObj = sessionObj.beginTransaction();
		if(sessionObj.isOpen() && sessionObj.isConnected()) {
			employeeObj = (Employee) sessionObj.get(Employee.class, employeeId);
			transObj.commit();
		}

		PrintWriter out = response.getWriter();
		response.setContentType("text/html");
		if(employeeObj != null) {
			out.print("<html><title>Hibernate Jndi Example</title><body><center><h2>Hibernate Jndi Example</h2></center><br /><h3>Employee Details</h3>");
			out.print("<table id='employeeTable' cellspacing=10 cellpadding=5><thead>");
			out.print("<th>Id</th>");
			out.print("<th>Name</th>");
			out.print("<th>Role</th>");

			out.print("</thead><tbody><tr>");
			out.print("<td>" + employeeId + "</td>");
			out.print("<td>" + employeeObj.getEmpName() + "</td>");
			out.print("<td>" + employeeObj.getEmpRole() + "</td>");
			out.print("</tr></tbody>");
			out.print("</table></body>");

			out.print("</html>");
		} else {
			out.print("<html><body><h2>No Employee Found with ID= "+ employeeId +"</h2></body></html>");
		}
	}
}

4. DataSource Configuration

Below are the steps involved in configuring the DataSource properties in the Hibernate and Tomcat configuration files.

4.1 Hibernate DataSource Configuration

To configure the hibernate framework, we need to implement configuration file i.e. hiberncate.cfg.xml. Right click on resources folder New -> Other

Fig. 16: Xml File Creation
Fig. 16: XML File Creation

A new pop window will open and select the wizard as XML file

Fig. 17: Wizard Selection
Fig. 17: Wizard Selection

Again, a pop-up window will open. Verify the parent folder location as HibernateJndi/src/main/resources and enter the file name as hibernate.cfg.xml. Click Finish.

Fig. 18: hibernate.cfg.xml
Fig. 18: hibernate.cfg.xml

Once the file is created, we will include the JNDI datasource configuration. Add the following code to it:

hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
   <session-factory>
      <!-- Database Connection Settings -->
      <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>    
      <property name="hibernate.connection.datasource">java:comp/env/jdbc/TestDb</property>
      <property name="show_sql">true</property>
      
      <!-- SQL Dialect -->
      <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
      
      <!-- Specifying Session Context -->
      <property name="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</property>
      
      <!-- Mapping With Model Class Containing Annotations -->
      <mapping class="com.jcg.hibernate.jndi.model.Employee" />
   </session-factory>
</hibernate-configuration>

Note: hibernate.connection.datasource property is used to provide the DataSource name that will be used by Hibernate for database operations.

4.2 Tomcat JNDI DataSource Configuration

For configuring Tomcat container to initialize DataSource, we need to make some changes in tomcat’s server.xml and context.xml files.

4.2.1 Configure Datasource in Tomcat – server.xml

Add the following resource element to the GlobalNamingResource element inside the $TOMCAT_HOME/conf/server.xml file. Here we are creating a resource of type javax.sql.DataSource with a JNDI name of jdbc/TestDb. Add the following code to it:

server.xml

<Resource name="jdbc/TestDb" auth="Container" type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/tutorialdb" username="root" password="" />

Note: We have kept the password value as blank for simplicity, however, it is pure unto user to keep it blank or set it during the MySQL configuration. If the user sets it, we need to provide the same password to this string.

4.2.2 Configure ResourceLink – context.xml

Next, we add the ResourceLink element to the Context element inside the $TOMCAT_HOME/conf/context.xml. This will create a linked resource to the global JNDI resource. Add the following code to it:

context.xml

<ResourceLink name="jdbc/TestDb" global="jdbc/TestDb" auth="Container" type="javax.sql.DataSource" />

At this point, we have successfully configured a DataSource in tomcat. When you run tomcat, the data source should be available under the JNDI name: jdbc/TestDb.

Note: Developers need to make sure that MySQL driver jar file is inside the tomcat’s $TOMCAT_HOME/lib directory, otherwise, it will not be able to create a database connection and we will get ClassNotFoundException in logs.

4.3 Preconfigured JNDI Datasource

We need to register the ResourceLink JNDI name (under which application will look up the preconfigured data source) inside the /WEB-INF/web.xml servlet descriptor of application.

I noticed this isn’t mandatory, but it helps to inform other developers about which data sources are available. Add the following code to it:

web.xml

<resource-ref>
      <description>MySQL Hibernate JNDI Datasource</description>
      <res-ref-name>jdbc/TestDb</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
</resource-ref>

5. Project Deploy

Once we are ready with all the changes done, lets compile and deploy the application on tomcat7 server. In order to deploy the application on Tomcat7, right-click on the project and navigate to Run as -> Run on Server

Fig. 19: How to Deploy Application on Tomcat
Fig. 19: How to Deploy Application on Tomcat

Tomcat will deploy the application in its webapps folder and shall start its execution to deploy the project so that we can go ahead and test it on the browser.

Fig. 20: Tomcat Processing
Fig. 20: Tomcat Processing

Open your favorite browser and hit the following URL,

http://localhost:8082/HibernateJndi/GetEmployeeById?empId=1

Server name (localhost) and port (8082) may vary as per your Tomcat configuration

6. Project Demo

Now, we are done with the application creation and it’s time to test out the application. Accessing the page, we will see the employee details.

Employee Id: 1

Fig. 21: Employee Details for Id #1
Fig. 21: Employee Details for Id #1

Employee Id: 2

Fig. 22: Employee Details for Id #2
Fig. 22: Employee Details for Id #2

Employee Id: 3

Fig. 23: Employee Details for Id #3
Fig. 23: Employee Details for Id #3

7. Conclusion

That’s all for Hibernate JNDI example for the Tomcat7 container. I hope it’s easy to understand and implement. Download the project from the below link and play around to learn more.

8. Download the Eclipse Project

This was a Hibernate JNDI example with Eclipse, MySQL, and Tomcat.

Download
You can download the full source code of this example here: Hibernate Jndi Example

Yatin

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button