How To Call Stored Procedure In Hibernate

What is STORED PROCEDURE?

A stored procedure is a pre-compiled SQL subroutine used to perform multiple procedural operations.

MySQL store procedure

Here’s a MySQL store procedure, which accept a stock code parameter and return the related stock data.
DELIMITER $$
 
CREATE PROCEDURE `GetStocks`(int_stockcode VARCHAR(20))
BEGIN
   SELECT * FROM stock WHERE stock_code = int_stockcode;
   END $$
 
DELIMITER ;
In MySQL, you can simple call it with a call keyword :
CALL GetStocks('7277');

How to call MSSQL and MYSQL stored procedure in Hibernate?

In Hibernate, there are two approaches to call a database store procedure.

1. Native SQL – createSQLQuery

You can use createSQLQuery() to call a store procedure directly.
Query query = session.createSQLQuery(
 "CALL GetStocks(:stockCode)")
 .addEntity(Stock.class)
 .setParameter("stockCode", "7277");
 
List result = query.list();
for(int i=0; i<result.size(); i++){
 Stock stock = (Stock)result.get(i);
 System.out.println(stock.getStockCode());
}


2. NamedNativeQuery in annotation

Declare your store procedure inside the @NamedNativeQueries annotation.
//Stock.java
...
@NamedNativeQueries({
 @NamedNativeQuery(
 name = "callStockStoreProcedure",
 query = "CALL GetStocks(:stockCode)",
 resultClass = Stock.class
 )
})
@Entity
@Table(name = "stock")
public class Stock implements java.io.Serializable {
...

Call it with getNamedQuery().
Query query = session.getNamedQuery("callStockStoreProcedure")
 .setParameter("stockCode", "7277");
List result = query.list();
for(int i=0; i<result.size(); i++){
 Stock stock = (Stock)result.get(i);
 System.out.println(stock.getStockCode());
}

The above approaches are doing the same thing, call a store procedure in database. There are not much big different between the three approaches, which method you choose is depend on your personal prefer.

How To Call Stored Procedure In Hibernate

How to load hibernate.cfg.xml from different directory

Hibernate XML configuration file “hibernate.cfg.xml” is always put at the root of your project classpath, outside of any package. If you place this configuration file into a different directory, you may encounter the following error :
(HibernateUtil.java:8)
 at com.mkyong.common.App.main(App.java:11)
Caused by: org.hibernate.HibernateException: /hibernate.cfg.xml not found
 at org.hibernate.util.ConfigHelper.getResourceAsStream(ConfigHelper.java:147)
 at org.hibernate.cfg.Configuration.getConfigurationInputStream(Configuration.java:1405)
 at org.hibernate.cfg.Configuration.configure(Configuration.java:1427)
 at org.hibernate.cfg.Configuration.configure(Configuration.java:1414)
 at com.mkyong.persistence.HibernateUtil.buildSessionFactory(HibernateUtil.java:13)
 ... 2 more

To ask Hibernate look for your “hibernate.cfg.xml” file in other directory, you can modify the default Hibernate’s SessionFactory class by passing your “hibernate.cfg.xml” file path as an argument into the configure() method:
SessionFactory sessionFactory = new AnnotationConfiguration().configure("/conf/hibernate.cfg.xml").buildSessionFactory();

Another alternate way to load “hibernate.cfg.xml” file is by using absolute path as below
 File f = new File("D:\\Workspace\\Kepler\\HibernateExamples\\conf\\hibernate.cfg.xml");
 SessionFactory sessionFactory = new AnnotationConfiguration().configure(f).buildSessionFactory();

HibernateUtil.java

Full Example in HibernateUtil.java, to load “hibernate.cfg.xml” from directory “/conf/“.
package com.tutorialsdesk.hibernate;

import java.io.File;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration; 

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

  private static SessionFactory buildSessionFactory() {
   try {
    //File f = new File("D:\\Workspace\\Kepler\\HibernateExamples\\conf\\hibernate.cfg.xml");
    return new AnnotationConfiguration().configure("/conf/hibernate.cfg.xml").buildSessionFactory(); 
   } catch (Throwable ex) {
    System.err.println("Initial SessionFactory creation failed." + ex);
    throw new ExceptionInInitializerError(ex);
   }
  }

  public static SessionFactory getSessionFactory() {
   return sessionFactory;
  }

  public static void shutdown() {
   getSessionFactory().close();
  }


}

How to load hibernate.cfg.xml from different directory

Hibernate Batch Processing Tutorial with examples

Consider a situation when you need to upload a large number of records into your database using Hibernate. Following is the code snippet to achieve this using Hibernate:
Session session = SessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
    Employee employee = new Employee(.....);
    session.save(employee);
}
tx.commit();
session.close();

Because by default, Hibernate will cache all the persisted objects in the session-level cache and ultimately your application would fall over with an OutOfMemoryException somewhere around the 50,000th row. You can resolve this problem if you are using batch processing with Hibernate.

To use the batch processing feature, first set hibernate.jdbc.batch_size as batch size to a number either at 20 or 50 depending on object size. This will tell the hibernate container that every X rows to be inserted as batch. To implement this in your code we would need to do little modification as follows:

Session session = SessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
    Employee employee = new Employee(.....);
    session.save(employee);
 if( i % 50 == 0 ) { // Same as the JDBC batch size
        //flush a batch of inserts and release memory:
        session.flush();
        session.clear();
    }
}
tx.commit();
session.close();

Above code will work fine for the INSERT operation, but if you are willing to make UPDATE operation then you can achieve using the following code:

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

ScrollableResults employeeCursor = session.createQuery("FROM EMPLOYEE")
                                   .scroll();
int count = 0;

while ( employeeCursor.next() ) {
   Employee employee = (Employee) employeeCursor.get(0);
   employee.updateEmployee();
   seession.update(employee); 
   if ( ++count % 50 == 0 ) {
      session.flush();
      session.clear();
   }
}
tx.commit();
session.close();

Batch Processing Example:

To use the batch processing feature, first set hibernate.jdbc.batch_size as 50. This will tell the hibernate container that every 50 rows to be inserted as batch. Also there is a slight change in the code.
<?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>
        <property name="hibernate.connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
        <property name="hibernate.connection.password">password</property>
        <property name="hibernate.connection.url">jdbc:jtds:sqlserver://localhost:1433/SBMUATDB</property>
        <property name="hibernate.connection.username">username</property>
        <property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>
     <property name="connection.pool_size">1</property>
        <property name="hbm2ddl.auto">create</property>
        <property name="show_sql">false</property>  
  <property name="format_sql">true</property>    
  <property name="hibernate.jdbc.batch_size">50</property>
  <mapping class="com.tutorialsdesk.hibernate.bean.Employee"/>

    </session-factory>
</hibernate-configuration>



Consider the following POJO Employee class:
package com.tutorialsdesk.hibernate.bean;

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.AUTO)
 @Column(name = "id")  
 private int id;
 
 @Column(name="first_name")  
 private String firstName;
 
 @Column(name="last_name")  
 private String lastName;
 
 @Column(name="salary")  
 private int salary;
 
 
 
 public Employee() {
  
 }
 
 public Employee(String firstName, String lastName, int salary) {
  super();
  this.firstName = firstName;
  this.lastName = lastName;
  this.salary = salary;
 }
 public int getId() {
  return id;
 }
 public void setId(int id) {
  this.id = id;
 }
 public String getFirstName() {
  return firstName;
 }
 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }
 public String getLastName() {
  return lastName;
 }
 public void setLastName(String lastName) {
  this.lastName = lastName;
 }
 public int getSalary() {
  return salary;
 }
 public void setSalary(int salary) {
  this.salary = salary;
 }
}


Let us create the following EMPLOYEE table to store Employee objects:
create table EMPLOYEE (
   id INT NOT NULL Identity PRIMARY KEY,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
)

Finally, we will create our application class with the main() method to run the application where we will use flush() and clear() methods available with Session object so that Hibernate keep writing these records into the database instead of caching them in the memory.

package com.tutorialsdesk.hibernate;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;

import com.tutorialsdesk.hibernate.bean.Employee;

public class ManageEmployee {

 private static SessionFactory factory; 
    public static void main(String[] args) {
       try{
          factory = new AnnotationConfiguration().configure().buildSessionFactory(); 
       }catch (Throwable ex) { 
          System.err.println("Failed to create sessionFactory object." + ex);
          throw new ExceptionInInitializerError(ex); 
       }
       ManageEmployee ME = new ManageEmployee();

       /* Add employee records in batches */
       ME.addEmployees( );
    }
    /* Method to create employee records in batches */
    public void addEmployees( ){
       Session session = factory.openSession();
       Transaction tx = null;
       Integer employeeID = null;
       try{
          tx = session.beginTransaction();
          for ( int i=0; i<100000; i++ ) {
             String fname = "First Name " + i;
             String lname = "Last Name " + i;
             Integer salary = i;
             Employee employee = new Employee(fname, lname, salary);
             session.save(employee);
           if( i % 50 == 0 ) {
            System.out.println("Flushed to DB");
                session.flush();
                session.clear();
             }
          }
          tx.commit();
       }catch (HibernateException e) {
          if (tx!=null) tx.rollback();
          e.printStackTrace(); 
       }finally {
          session.close(); 
       }
       return ;
    }

}

Hibernate Batch Processing Tutorial with examples

Hibernate Criteria Tutorial with examples

Hibernate provides alternate ways of manipulating objects and in turn data available in RDBMS tables. One of the methods is Criteria API which allows you to build up a criteria query object programmatically where you can apply filtration rules and logical conditions.

The Hibernate Session interface provides createCriteria() method which can be used to create a Criteria object that returns instances of the persistence object's class when your application executes a criteria query.

Following is the simplest example of a criteria query is one which will simply return every object that corresponds to the Employee class.

Criteria cr = session.createCriteria(Employee.class);
List results = cr.list();

Restrictions with Criteria:

You can use add() method available for Criteria object to add restriction for a criteria query. Following is the example to add a restriction to return the records with salary is equal to 2000:

Criteria cr = session.createCriteria(Employee.class);
cr.add(Restrictions.eq("salary", 2000));
List results = cr.list();
Following are the few more examples covering different scenarios and can be used as per requirement:
Criteria cr = session.createCriteria(Employee.class);

// To get records having salary more than 2000
cr.add(Restrictions.gt("salary", 2000));

// To get records having salary less than 2000
cr.add(Restrictions.lt("salary", 2000));

// To get records having fistName starting with zara
cr.add(Restrictions.like("firstName", "zara%"));

// Case sensitive form of the above restriction.
cr.add(Restrictions.ilike("firstName", "zara%"));

// To get records having salary in between 1000 and 2000
cr.add(Restrictions.between("salary", 1000, 2000));

// To check if the given property is null
cr.add(Restrictions.isNull("salary"));

// To check if the given property is not null
cr.add(Restrictions.isNotNull("salary"));

// To check if the given property is empty
cr.add(Restrictions.isEmpty("salary"));

// To check if the given property is not empty
cr.add(Restrictions.isNotEmpty("salary"));
You can create AND or OR conditions using LogicalExpression restrictions as follows:
Criteria cr = session.createCriteria(Employee.class);

Criterion salary = Restrictions.gt("salary", 2000);
Criterion name = Restrictions.ilike("firstNname","zara%");

// To get records matching with OR condistions
LogicalExpression orExp = Restrictions.or(salary, name);
cr.add( orExp );


// To get records matching with AND condistions
LogicalExpression andExp = Restrictions.and(salary, name);
cr.add( andExp );

List results = cr.list();
Though all the above conditions can be used directly with HQL as explained in previous tutorial.

Pagination using Criteria:

There are two methods of the Criteria interface for pagination.
  1. public Criteria setFirstResult(int firstResult) This method takes an integer that represents the first row in your result set, starting with row 0.
  2. public Criteria setMaxResults(int maxResults) This method tells Hibernate to retrieve a fixed number maxResults of objects.
Using above two methods together, we can construct a paging component in our web or Swing application. Following is the example which you can extend to fetch 10 rows at a time:
Criteria cr = session.createCriteria(Employee.class);
cr.setFirstResult(1);
cr.setMaxResults(10);
List results = cr.list();

Sorting the Results:

The Criteria API provides the org.hibernate.criterion.Order class to sort your result set in either ascending or descending order, according to one of your object's properties. This example demonstrates how you would use the Order class to sort the result set:
Criteria cr = session.createCriteria(Employee.class);
// To get records having salary more than 2000
cr.add(Restrictions.gt("salary", 2000));

// To sort records in descening order
crit.addOrder(Order.desc("salary"));

// To sort records in ascending order
crit.addOrder(Order.asc("salary"));

List results = cr.list();

Projections & Aggregations:

The Criteria API provides the org.hibernate.criterion.Projections class which can be used to get average, maximum or minimum of the property values. The Projections class is similar to the Restrictions class in that it provides several static factory methods for obtaining Projection instances.

Following are the few examples covering different scenarios and can be used as per requirement:
Criteria cr = session.createCriteria(Employee.class);

// To get total row count.
cr.setProjection(Projections.rowCount());

// To get average of a property.
cr.setProjection(Projections.avg("salary"));

// To get distinct count of a property.
cr.setProjection(Projections.countDistinct("firstName"));

// To get maximum of a property.
cr.setProjection(Projections.max("salary"));

// To get minimum of a property.
cr.setProjection(Projections.min("salary"));

// To get sum of a property.
cr.setProjection(Projections.sum("salary"));



Hope we are able to explain you Hibernate Criteria, if you have any questions or suggestions please write to us using contact us form.(Second Menu from top left).

Please share us on social media if you like the tutorial.
Hibernate Criteria Tutorial with examples

Hibernate Named Query Tutorial with examples

Named queries in hibernate is a technique to group the HQL statements in single location, and lately refer them by some name whenever need to use them. It helps largely in code cleanup because these HQL statements are no longer scattered in whole code.

Advantages of named queries:

below are some minor advantages of named queries:
  1. Fail fast: Their syntax is checked when the session factory is created, making the application fail fast in case of an error.
  2. Reusable: They can be accessed and used from several places which increase re-usability.

How to declare named query in Hibernate using Annotaions

Hibernate Named Queries can be defined in Hibernate mapping files or through the use of JPA annotations @NamedQuery and @NamedNativeQuery.

HQL in annotation

@NamedQueries({
 @NamedQuery(
 name = "findStockByStockCode",
 query = "from Stock s where s.stockCode = :stockCode"
 )
})
@Entity
@Table(name = "stock")
public class Stock implements java.io.Serializable {

// 

}

Native SQL in annotation

@NamedNativeQueries({
 @NamedNativeQuery(
 name = "findStockByStockCodeNativeSQL",
 query = "select * from stock s where s.stock_code = :stockCode",
        resultClass = Stock.class
 )
})
@Entity
@Table(name = "stock")
public class Stock implements java.io.Serializable {
//
}

In native SQL, you have to declare the ‘resultClass‘ to let Hibernate know what is the return type, failed to do it will caused the exception “org.hibernate.cfg.NotYetImplementedException: Pure native scalar queries are not yet supported“.

Call a named query

In Hibernate, you can call the named query via getNamedQuery method.
Query query = session.getNamedQuery("findStockByStockCode").setString("stockCode", "7277");
Query query = session.getNamedQuery("findStockByStockCodeNativeSQL").setString("stockCode", "7277");

Named queries are global access, which means the name of a query have to be unique in annotations. In real environment, it’s always good practice to isolate all the named queries into their own file. In addition, named queries stored in the Hibernate mapping files or annotation are more easier to maintain than queries scattered through the Java code.

Hope we are able to explain you Hibernate Named Query, if you have any questions or suggestions please write to us using contact us form.(Second Menu from top left).

Please share us on social media if you like the tutorial.
Hibernate Named Query Tutorial with examples

Hibernate Query Language (HQL) Tutorial with examples

Hibernate Query Language (HQL) is an object-oriented query language, similar to SQL, but instead of operating on tables and columns, HQL works with persistent objects and their properties. HQL queries are translated by Hibernate into conventional SQL queries which in turns perform action on database.

Although you can use SQL statements directly with Hibernate using Native SQL but I would recommend to use HQL whenever possible to avoid database portability hassles, and to take advantage of Hibernate's SQL generation and caching strategies.

Keywords like SELECT , FROM and WHERE etc. are not case sensitive but properties like table and column names are case sensitive in HQL.

FROM Clause

You will use FROM clause if you want to load a complete persistent objects into memory. Following is the simple syntax of using FROM clause:
String hql = "FROM Employee";
Query query = session.createQuery(hql);
List results = query.list();

If you need to fully qualify a class name in HQL, just specify the package and class name as follows:
String hql = "FROM com.hibernatebook.criteria.Employee";
Query query = session.createQuery(hql);
List results = query.list();

AS Clause

The AS clause can be used to assign aliases to the classes in your HQL queries, specially when you have long queries. For instance, our previous simple example would be the following:
String hql = "FROM Employee AS E";
Query query = session.createQuery(hql);
List results = query.list();

The AS keyword is optional and you can also specify the alias directly after the class name, as follows:
String hql = "FROM Employee E";
Query query = session.createQuery(hql);
List results = query.list();

SELECT Clause

The SELECT clause provides more control over the result set than the from clause. If you want to obtain few properties of objects instead of the complete object, use the SELECT clause. Following is the simple syntax of using SELECT clause to get just first_name field of the Employee object:
String hql = "SELECT E.firstName FROM Employee E";
Query query = session.createQuery(hql);
List results = query.list();It is notable here that Employee.firstName is a property of Employee object rather than a field of the EMPLOYEE table.

WHERE Clause

If you want to narrow the specific objects that are returned from storage, you use the WHERE clause. Following is the simple syntax of using WHERE clause:
String hql = "FROM Employee E WHERE E.id = 10";
Query query = session.createQuery(hql);
List results = query.list();

ORDER BY Clause

To sort your HQL query's results, you will need to use the ORDER BY clause. You can order the results by any property on the objects in the result set either ascending (ASC) or descending (DESC). Following is the simple syntax of using ORDER BY clause:
String hql = "FROM Employee E WHERE E.id > 10 ORDER BY E.salary DESC";
Query query = session.createQuery(hql);
List results = query.list();
If you wanted to sort by more than one property, you would just add the additional properties to the end of the order by clause, separated by commas as follows:
String hql = "FROM Employee E WHERE E.id > 10 " +
             "ORDER BY E.firstName DESC, E.salary DESC ";
Query query = session.createQuery(hql);
List results = query.list();

GROUP BY Clause

This clause lets Hibernate pull information from the database and group it based on a value of an attribute and, typically, use the result to include an aggregate value. Following is the simple syntax of using GROUP BY clause:
String hql = "SELECT SUM(E.salary), E.firtName FROM Employee E " +
             "GROUP BY E.firstName";
Query query = session.createQuery(hql);
List results = query.list();

Using Named Paramters

Hibernate supports named parameters in its HQL queries. This makes writing HQL queries that accept input from the user easy and you do not have to defend against SQL injection attacks. Following is the simple syntax of using named parameters:
String hql = "FROM Employee E WHERE E.id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("employee_id",10);
List results = query.list();

UPDATE Clause

Bulk updates are new to HQL with Hibernate 3, and deletes work differently in Hibernate 3 than they did in Hibernate 2. The Query interface now contains a method called executeUpdate() for executing HQL UPDATE or DELETE statements.

The UPDATE clause can be used to update one or more properties of an one or more objects. Following is the simple syntax of using UPDATE clause:
String hql = "UPDATE Employee set salary = :salary "  + 
             "WHERE id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("salary", 1000);
query.setParameter("employee_id", 10);
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);

DELETE Clause

The DELETE clause can be used to delete one or more objects. Following is the simple syntax of using DELETE clause:
String hql = "DELETE FROM Employee "  + 
             "WHERE id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("employee_id", 10);
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);

INSERT Clause

HQL supports INSERT INTO clause only where records can be inserted from one object to another object. Following is the simple syntax of using INSERT INTO clause:
String hql = "INSERT INTO Employee(firstName, lastName, salary)"  + 
             "SELECT firstName, lastName, salary FROM old_employee";
Query query = session.createQuery(hql);
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);

Aggregate Methods

HQL supports a range of aggregate methods, similar to SQL. They work the same way in HQL as in SQL and following is the list of the available functions:
  1. avg(property name) The average of a property's value
  2. count(property name or *) The number of times a property occurs in the results
  3. max(property name) The maximum value of the property values
  4. min(property name) The minimum value of the property values
  5. sum(property name) The sum total of the property values
The distinct keyword only counts the unique values in the row set. The following query will return only unique count:
String hql = "SELECT count(distinct E.firstName) FROM Employee E";
Query query = session.createQuery(hql);
List results = query.list();

Pagination using Query

There are two methods of the Query interface for pagination.
  1. Query setFirstResult(int startPosition) This method takes an integer that represents the first row in your result set, starting with row 0.
  2. Query setMaxResults(int maxResult) This method tells Hibernate to retrieve a fixed number maxResults of objects.
Using above two methods together, we can construct a paging component in our web or Swing application. Following is the example which you can extend to fetch 10 rows at a time:
String hql = "FROM Employee";
Query query = session.createQuery(hql);
query.setFirstResult(1);
query.setMaxResults(10);
List results = query.list();

Hope we are able to explain you Hibernate Query Language (HQL), if you have any questions or suggestions please write to us using contact us form.(Second Menu from top left).

Please share us on social media if you like the tutorial.
Hibernate Query Language (HQL) Tutorial with examples

Hibernate Caching Tutorial with Examples


Caching in Hibernate

One of the major benefit of using Hibernate in large application is it’s support for caching, hence reducing database queries and better performance.

Caching is all about application performance optimization and it sits between your application and the database to avoid the number of database hits as many as possible to give a better performance for performance critical applications.

Caching is important to Hibernate as well which utilizes a multilevel caching schemes as explained below:
Hibernate Caching Tutorial with Examples

First-level cache:

The first-level cache is the Session cache and is a mandatory cache through which all requests must pass. The Session object keeps an object under its own power before committing it to the database.

If you issue multiple updates to an object, Hibernate tries to delay doing the update as long as possible to reduce the number of update SQL statements issued. If you close the session, all the objects being cached are lost and either persisted or updated in the database.

Query-level cache:

Hibernate also implements a cache for query resultsets that integrates closely with the second-level cache.

This is an optional feature and requires two additional physical cache regions that hold the cached query results and the timestamps when a table was last updated. This is only useful for queries that are run frequently with the same parameters.

Second-level cache:

Second level cache is an optional cache and first-level cache will always be consulted before any attempt is made to locate an object in the second-level cache. The second-level cache can be configured on a per-class and per-collection basis and mainly responsible for caching objects across sessions.

Any third-party cache can be used with Hibernate. An org.hibernate.cache.CacheProvider interface is provided, which must be implemented to provide Hibernate with a handle to the cache implementation.

Hibernate uses first-level cache by default and you have nothing to do to use first-level cache. Let's go straight to the optional second-level cache. Not all classes benefit from caching, so it's important to be able to disable the second-level cache.

The Hibernate second-level cache is set up in two steps. First, you have to decide which concurrency strategy to use. After that, you configure cache expiration and physical cache attributes using the cache provider.

Concurrency strategies:

A concurrency strategy is a mediator which responsible for storing items of data in the cache and retrieving them from the cache. If you are going to enable a second-level cache, you will have to decide, for each persistent class and collection, which cache concurrency strategy to use.
  • Transactional: Use this strategy for read-mostly data where it is critical to prevent stale data in concurrent transactions,in the rare case of an update.
  • Read-write: Again use this strategy for read-mostly data where it is critical to prevent stale data in concurrent transactions,in the rare case of an update.
  • Nonstrict-read-write: This strategy makes no guarantee of consistency between the cache and the database. Use this strategy if data hardly ever changes and a small likelihood of stale data is not of critical concern.
  • Read-only: A concurrency strategy suitable for data which never changes. Use it for reference data only.

Hibernate Configuration for Second Level EHCache

Second level cache is disabled by default in hibernate, so we would need to enable it and add some configurations to get it working. Our hibernate.cfg.xml file looks like below.
<?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>
        <property name="hibernate.connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
        <property name="hibernate.connection.password">SBMDB@08$2012</property>
        <property name="hibernate.connection.url">jdbc:jtds:sqlserver://172.16.5.23:1433/SBMUATDB</property>
        <property name="hibernate.connection.username">SBM_QA</property>
        <property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>
     <property name="connection.pool_size">1</property>
        <property name="hbm2ddl.auto">create</property>
        <property name="show_sql">true</property>  
  <property name="format_sql">true</property>  
  
  <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>                  
   <!-- For singleton factory -->        
   <!-- <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</property>          -->      
  <!-- enable second level cache and query cache -->         
  <property name="hibernate.cache.use_second_level_cache">true</property>  
  <property name="hibernate.cache.use_query_cache">true</property>          
  <property name="net.sf.ehcache.configurationResourceName">/myehcache.xml</property>   
  
        <mapping class="com.tutorialsdesk.hibernate.bean.Student"/>
        <mapping class="com.tutorialsdesk.hibernate.bean.StudentMarksDetails"/>
       <!--  <mapping class="com.tutorialsdesk.hibernate.bean.StudentAddress"/>  -->
    </session-factory>
</hibernate-configuration>


Some important points about hibernate configurations are:
  1. hibernate.cache.region.factory_class is used to define the Factory class for Second level caching, I am using org.hibernate.cache.ehcache.EhCacheRegionFactory for this. If you want the factory class to be singleton, you should use org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory class. If you are using Hibernate 3, corresponding classes will be net.sf.ehcache.hibernate.EhCacheRegionFactory and net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory.
  2. hibernate.cache.use_second_level_cache is used to enable the second level cache.
  3. hibernate.cache.use_query_cache is used to enable the query cache, without it HQL queries results will not be cached.
  4. net.sf.ehcache.configurationResourceName is used to define the EHCache configuration file location, it’s an optional parameter and if it’s not present EHCache will try to locate ehcache.xml file in the application classpath.

EHCache Configuration File

Our EHCache configuration file looks like below.
<?xml version="1.0" encoding="UTF-8"?> 
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"    monitoring="autodetect" dynamicConfig="true">       
<diskStore path="java.io.tmpdir/ehcache" />      
 <defaultCache maxEntriesLocalHeap="10000" eternal="false"        timeToIdleSeconds="120" timeToLiveSeconds="120" diskSpoolBufferSizeMB="30"        maxEntriesLocalDisk="10000000" diskExpiryThreadIntervalSeconds="120"        memoryStoreEvictionPolicy="LRU" statistics="true">         
 <persistence strategy="localTempSwap" />     
 </defaultCache>       
 <cache name="employee" maxEntriesLocalHeap="10000" eternal="false"        timeToIdleSeconds="5" timeToLiveSeconds="10">         
 <persistence strategy="localTempSwap" />    
  </cache>       
  <cache name="org.hibernate.cache.internal.StandardQueryCache"        maxEntriesLocalHeap="5" eternal="false" timeToLiveSeconds="120">         
  <persistence strategy="localTempSwap" />    
   </cache>       
   <cache name="org.hibernate.cache.spi.UpdateTimestampsCache"        maxEntriesLocalHeap="5000" eternal="true">        
    <persistence strategy="localTempSwap" />     
    </cache> 
    </ehcache> 


That's it, now we have second-level caching enabled for the Employee class and Hibernate now hits the second-level cache whenever you navigate to a Employee or when you load a Employee by identifier.

You should analyze your all the classes and choose appropriate caching strategy for each of the classes. Sometime, second-level caching may downgrade the performance of the application. So it is recommended to benchmark your application first without enabling caching and later on enable your well suited caching and check the performance. If caching is not improving system performance then there is no point in enabling any type of caching.

Enable Hibernate Second Level Cache at Table Level by Annotation

In Hibernate Annotation, we use @Cache to set table level cache. We also need to set @Cacheable. The class CacheConcurrencyStrategy of the package org.hibernate.annotations, provides the caching.
@Entity
@Table(name="college")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Employee implements Serializable {


// Implementions 

}

Enable Hibernate Second Level Cache at Column Level by Annotation

In Hibernate Collections to cache the collection at column level @Cache is used and CacheConcurrencyStrategy class provides the caching. We need to set it at property level in our entity.
   @ElementCollection
 @CollectionTable(name="student", joinColumns=@JoinColumn(name="college_id"))
 @Column(name="student_name")
 @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
 private Set<String> students;

Enable Hibernate Query-level Cache:

To use the query cache, you must first activate it using the hibernate.cache.use_query_cache="true" property in the configuration file. By setting this property to true, you make Hibernate create the necessary caches in memory to hold the query and identifier sets.

Next, to use the query cache, you use the setCacheable(Boolean) method of the Query class. For example:
Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
List users = query.list();
SessionFactory.closeSession();

Hibernate also supports very fine-grained cache support through the concept of a cache region. A cache region is part of the cache that's given a name.
Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
query.setCacheRegion("employee");
List users = query.list();
SessionFactory.closeSession();

This code uses the method to tell Hibernate to store and look for the query in the employee area of the cache.

Hope we are able to explain you Caching in Hibernate, if you have any questions or suggestions please write to us using contact us form.(Second Menu from top left).

Please share us on social media if you like the tutorial.

Hibernate Transaction Management Tutorial with Examples

Hibernate Transaction Management

A transaction simply represents a unit of work. In such case, if one step fails, the whole transaction fails (which is termed as atomicity). A transaction can be described by ACID properties (Atomicity, Consistency, Isolation and Durability).

Hibernate Transaction Management Tutorial with Examples

Transaction Interface in Hibernate

In hibernate framework, we have Transaction interface that defines the unit of work. It maintains abstraction from the transaction implementation (JTA,JDBC).

A transaction is associated with Session and instantiated by calling session.beginTransaction().

The methods of Transaction interface are as follows:

  1. void begin() starts a new transaction.
  2. void commit() ends the unit of work unless we are in FlushMode.NEVER.
  3. void rollback() forces this transaction to rollback.
  4. void setTimeout(int seconds) it sets a transaction timeout for any transaction started by a subsequent call to begin on this instance.
  5. boolean isAlive() checks if the transaction is still alive.
  6. void registerSynchronization(Synchronization s) registers a user synchronization callback for this transaction.
  7. boolean wasCommited() checks if the transaction is commited successfully.
  8. boolean wasRolledBack() checks if the transaction is rolledback successfully.

Example of Transaction Management in Hibernate

This is the basic structure that your Hibernate programs should have, conserning transaction handling:
 Session session = null;
 Transaction tx  = null;

 try{
  session = HibernateUtil.getSessionFactory().openSession();
  tx = session.beginTransaction();
  tx.setTimeout(5);
  tx.commit();

 }catch(RuntimeException e){
  try{
   tx.rollback();
  }catch(RuntimeException rbe){
   rbe.printStackTrace();   
   tx.rollback();   

  }
  throw e;
 }finally{
  if(session!=null){
   session.close();
  }
 }
 }

Here as you can see whenever a RuntimeException happens we call rollback() API call that forces the rollback of the transaction. This means that every operation of that specific transaction that occured before the Exception, will be canceled and the database will return in its state before these operations took place.

Hope we are able to explain you Hibernate Transaction Management, if you have any questions or suggestions please write to us using contact us form.(Second Menu from top left).

Please share us on social media if you like the tutorial.

Hibernate Many-To-Many Mapping Using Java Annotations Tutorial with Examples

Many To Many Relationship

A Many To Many relationship in Java is where the source object has an attribute that stores a collection of target objects and (if) those target objects had the inverse relationship back to the source object it would also be a ManyToMany relationship.

All ManyToMany relationships require a JoinTable. The JoinTable is defined using the @JoinTable annotation and XML element. The JoinTable defines a foreign key to the source object’s primary key (joinColumns), and a foreign key to the target object’s primary key (inverseJoinColumns). Normally the primary key of the JoinTable is the combination of both foreign keys.

Creating Database

Before we start lets create a simple database and table to apply hibernate operations on. Copy and Paste the following sql query in your query editor and execute.
CREATE table STUDENT (student_id int identity NOT NULL PRIMARY KEY,
rollno varchar(20),
firstname varchar(50),
lastname varchar(50),
course varchar(50))

CREATE TABLE STUDENT_MARKS_DETAILS (student_id int NOT NULL  FOREIGN KEY REFERENCES STUDENT (student_id),
test_id int NOT NULL identity PRIMARY KEY, 
subject varchar(100) DEFAULT NULL, 
max_marks varchar(100) DEFAULT NULL, 
marks_obtained varchar(100) DEFAULT NULL,
result varchar(100) DEFAULT NULL 
)

CREATE TABLE STUDENT_TEST (   
student_id int NOT NULL FOREIGN KEY REFERENCES STUDENT (student_id),  
test_id int NOT NULL FOREIGN KEY REFERENCES STUDENT_MARKS_DETAILS (test_id),
PRIMARY KEY (student_id,test_id),   
) 

NOTE : Above script is written for SQL Server, you can change accordingly for different DB.

Adding Hibernate Jars

Download latest Hibernate jars from here http://hibernate.org/ and add to your classpath. Create Model Classes As a next step let’s create the model classes Student.java and StudentMarksDetails.java using Annotations. The contents of the model classes are as below

Student.java

package com.tutorialsdesk.hibernate.bean;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType;
import javax.persistence.Id; 
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;    
import javax.persistence.UniqueConstraint;
import javax.persistence.JoinColumn;
@Entity 
@Table(name="STUDENT",uniqueConstraints = { @UniqueConstraint(columnNames = "student_id") }) 

public class Student implements Serializable {

 private static final long serialVersionUID = 5502738307095121008L;

 @Id   
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "student_id")  
 private int id;
 
 @Column(name="rollno")   
 private String rollno;
 
 @Column(name="firstname")   
 private String firstname;
 
 @Column(name="lastname")     
 private String lastname;
 
 @Column(name="course")   
 private String course;
    
  // @OneToOne(cascade = CascadeType.ALL)  
 //@PrimaryKeyJoinColumn 
 //private StudentAddress address;
    
 @ManyToMany(cascade = { CascadeType.ALL })   
 @JoinTable(name = "STUDENT_TEST", joinColumns = {
   @JoinColumn(name = "STUDENT_ID") },
   inverseJoinColumns = { @JoinColumn(name = "TEST_ID") })   
 private Set<StudentMarksDetails> studentMarksDetails = new HashSet<StudentMarksDetails>();   

    
    public Student(){
     
    }
    
 public Student(String rollno, String firstname, String lastname,
   String course) {
  super();
  this.rollno = rollno;
  this.firstname = firstname;
  this.lastname = lastname;
  this.course = course;
  //this.address = address;
 }
 @Override  
 public boolean equals(Object emp) {   
   if (emp instanceof Student) {   
    Student student = (Student) emp;   
   
    if (this.firstname.equals(student.getFirstname())   
      && this.lastname.equals(student.getLastname())   
      && this.rollno.equals(student.getRollno())   
      && this.course.equals(student.getCourse()))   
     return true;   
   }   
   
   return false;   
  }   

 @Override  
 public int hashCode() {   
  
 return this.firstname.hashCode() + this.lastname.hashCode()   
  + this.rollno.hashCode() + this.course.hashCode();   
  }   


 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getRollno() {
  return rollno;
 }

 public void setRollno(String rollno) {
  this.rollno = rollno;
 }

 public String getFirstname() {
  return firstname;
 }

 public void setFirstname(String firstname) {
  this.firstname = firstname;
 }

 public String getLastname() {
  return lastname;
 }

 public void setLastname(String lastname) {
  this.lastname = lastname;
 }

 public String getCourse() {
  return course;
 }

 public void setCourse(String course) {
  this.course = course;
 }

 /*public StudentAddress getAddress() {
  return address;
 }

 public void setAddress(StudentAddress address) {
  this.address = address;
 }
*/
 public Set<StudentMarksDetails> getMarksDetails() {
  return studentMarksDetails;
 }

 public void setMarksDetails(Set<StudentMarksDetails> marksDetails) {
  this.studentMarksDetails = marksDetails;
 }


 
}


StudentMarksDetails.java

package com.tutorialsdesk.hibernate.bean;

import java.util.HashSet;
import java.util.Set;

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

@Entity
@Table(name = "STUDENT_MARKS_DETAILS")
public class StudentMarksDetails {

 @Id
 @GeneratedValue
 @Column(name = "test_id")
 private long testId;

 @Column(name = "subject")
 private String subject;

 @Column(name = "max_marks")
 private String maxMarks;

 @Column(name = "marks_obtained")
 private String marksObtained;

 @Column(name = "result")
 private String result;
 
 @ManyToMany(mappedBy = "studentMarksDetails")   
private Set<Student> student = new HashSet<Student>();  
 
 
 public StudentMarksDetails() {
 }

 public StudentMarksDetails(String subject, String maxMarks, String marksObtained,
   String result) {
  this.subject = subject;
  this.maxMarks = maxMarks;
  this.marksObtained = marksObtained;
  this.result = result;
 }

 public long getTestId() {
  return testId;
 }

 public void setTestId(long testId) {
  this.testId = testId;
 }

 public String getSubject() {
  return subject;
 }

 public void setSubject(String subject) {
  this.subject = subject;
 }

 public String getMaxMarks() {
  return maxMarks;
 }

 public void setMaxMarks(String maxMarks) {
  this.maxMarks = maxMarks;
 }

 public String getMarksObtained() {
  return marksObtained;
 }

 public void setMarksObtained(String marksObtained) {
  this.marksObtained = marksObtained;
 }

 public String getResult() {
  return result;
 }

 public void setResult(String result) {
  this.result = result;
 }

 public Set<Student> getStudent() {   
  return student;   
}   

 public void setStudent(Set<Student> student) {   
  this.student = student;   
 }   


}

Adding Hibernate Configuration file

The hibernate.cfg.xml is as follows:
<?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>
        <property name="hibernate.connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
        <property name="hibernate.connection.password">password</property>
        <property name="hibernate.connection.url">jdbc:jtds:sqlserver://localhost:1433/SBMUATDB</property>
        <property name="hibernate.connection.username">username</property>
        <property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>
     <property name="connection.pool_size">1</property>
        <property name="hbm2ddl.auto">create</property>
        <property name="show_sql">true</property>  
  <property name="format_sql">true</property>  
        <mapping class="com.tutorialsdesk.hibernate.bean.Student"/>
        <mapping class="com.tutorialsdesk.hibernate.bean.StudentMarksDetails"/>
       <!--  <mapping class="com.tutorialsdesk.hibernate.bean.StudentAddress"/>  -->
    </session-factory>
</hibernate-configuration>



In the above file we have set the database connection to SQL Server database . The show_sql option, if set to true will display all the executed SQL queries on the console. The property hbm2ddl.auto , if set to create, creates the schema, destroying the previous data.

Note : In case you want to use any other database then, you need to change these properties – “dialect”, “connection.driver_class”, “connection.url”, “connection.username”, and “connection.password”.

Also we have added the Annotation based entity classes Student.java and StudentMarksDetails.java to the above file.

Create Utility class

Next, we will write a utility class to take care of Hibernate start up and retrieve the session easily. We will write the file HibernateUtil.java as below:
package com.tutorialsdesk.hibernate;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration; 

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

  private static SessionFactory buildSessionFactory() {
   try {
    return new AnnotationConfiguration().configure().buildSessionFactory(); 
   } catch (Throwable ex) {
    System.err.println("Initial SessionFactory creation failed." + ex);
    throw new ExceptionInInitializerError(ex);
   }
  }

  public static SessionFactory getSessionFactory() {
   return sessionFactory;
  }

  public static void shutdown() {
   getSessionFactory().close();
  }


}


Main AnnotationTest class

This class tests the Many-to-Many relationship by creating and listing the student details and corresponding addresses as below:
package com.tutorialsdesk.hibernate;

import java.util.ArrayList;

import org.hibernate.*;

import com.tutorialsdesk.hibernate.bean.Student;
import com.tutorialsdesk.hibernate.bean.StudentMarksDetails;

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

   session.beginTransaction();

   Student student1 = new Student("2013HZ58073","Amit","Sharma","B.Tech");
   Student student2 = new Student("2013HZ58075", "Sweta", "Nagpal","MCA");

   StudentMarksDetails test1 = new StudentMarksDetails("Maths", "100", "87", "Passed");
   StudentMarksDetails test2 = new StudentMarksDetails("Science", "100", "90", "Passed");

   student1.getMarksDetails().add(test1);
   student1.getMarksDetails().add(test2);
   student2.getMarksDetails().add(test1);
   student2.getMarksDetails().add(test2);

   session.save(student1);
   session.save(student2);

   session.getTransaction().commit();
   session.close();

 
}
}


Hibernate Many-To-Many Mapping Using Java Annotations Tutorial with Examples
Hope we are able to explain you Hibernate Many-To-Many Mapping Using Java Annotations, if you have any questions or suggestions please write to us using contact us form.(Second Menu from top left).

Please share us on social media if you like the tutorial.

Hibernate One-To-Many Mapping Using Java Annotations Tutorial with Examples


One To Many Relationship

Also known as a many-to-one relationship, this occurs when the maximum of one multiplicity is one and the other is greater than one. An example is the relationship between Student and Marks_Details. Consider the following relationship:
Hibernate One-To-Many Mapping Using Java Annotations Tutorial with Examples

According to the relationship each Student can have a any number of marks_Details. But each marks_Details will be associated with only one Student. Hence we will need two tables namely STUDENT and MARKS_DETAILS to create this relation. In Hibernate, one-to-many relationship between entities can be created by 2 different techniques. These techniques are:
  1. Using foreign key association:

    In this association, we can have a foreign key column in MARKS_DETAILS table i.e student_id. This column will refer to primary key of STUDENT table. This way no two Marks Details can be associated with multiple students. Obviously, Marks Details needs to be unique for enforcing this restriction. The example below in this post demonstrates this asscociation.
  2. Using a common join table:

    In this association, we can have a common join table lets say STUDENT_MARKS_DETAILS. This table will have two column i.e. student_id which will be foreign key referring to primary key in STUDENT table and similarly MARKSID which will be foreign key referring to primary key of MARKS_DETAILS table.

Creating Database

Before we start lets create a simple database and table to apply hibernate operations on. Copy and Paste the following sql query in your query editor and execute.
CREATE table STUDENT (student_id int identity NOT NULL PRIMARY KEY,
rollno varchar(20),
firstname varchar(50),
lastname varchar(50),
course varchar(50))

CREATE TABLE STUDENT_MARKS_DETAILS (student_id int NOT NULL PRIMARY KEY FOREIGN KEY REFERENCES STUDENT (student_id),
test_id int NOT NULL identity, 
subject varchar(100) DEFAULT NULL, 
max_marks varchar(100) DEFAULT NULL, 
marks_obtained varchar(100) DEFAULT NULL,
result varchar(100) DEFAULT NULL 
)




NOTE : Above script is written for SQL Server, you can change accordingly for different DB.

Adding Hibernate Jars

Download latest Hibernate jars from here http://hibernate.org/ and add to your classpath.
Create Model Classes As a next step let’s create the model classes Student.java and StudentMarksDetails.java using Annotations.
The contents of the model classes are as below
Student.java
package com.tutorialsdesk.hibernate.bean;

import java.io.Serializable;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType;
import javax.persistence.Id; 
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;    
import javax.persistence.UniqueConstraint;
@Entity 
@Table(name="STUDENT",uniqueConstraints = { @UniqueConstraint(columnNames = "student_id") }) 

public class Student implements Serializable {

 private static final long serialVersionUID = 5502738307095121008L;

 @Id   
 @GeneratedValue(strategy = GenerationType.AUTO)
 @Column(name = "student_id")  
 private int id;
 
 @Column(name="rollno")   
 private String rollno;
 
 @Column(name="firstname")   
 private String firstname;
 
 @Column(name="lastname")     
 private String lastname;
 
 @Column(name="course")   
 private String course;
    
  // @OneToOne(cascade = CascadeType.ALL)  
 //@PrimaryKeyJoinColumn 
 //private StudentAddress address;
    
    @OneToMany(mappedBy = "student")   
    private Set<StudentMarksDetails> marksDetails;   

    
    public Student(){
     
    }
    
 public Student(String rollno, String firstname, String lastname,
   String course, StudentAddress address) {
  super();
  this.rollno = rollno;
  this.firstname = firstname;
  this.lastname = lastname;
  this.course = course;
  //this.address = address;
 }



 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getRollno() {
  return rollno;
 }

 public void setRollno(String rollno) {
  this.rollno = rollno;
 }

 public String getFirstname() {
  return firstname;
 }

 public void setFirstname(String firstname) {
  this.firstname = firstname;
 }

 public String getLastname() {
  return lastname;
 }

 public void setLastname(String lastname) {
  this.lastname = lastname;
 }

 public String getCourse() {
  return course;
 }

 public void setCourse(String course) {
  this.course = course;
 }

 /*public StudentAddress getAddress() {
  return address;
 }

 public void setAddress(StudentAddress address) {
  this.address = address;
 }
*/
 public Set<StudentMarksDetails> getMarksDetails() {
  return marksDetails;
 }

 public void setMarksDetails(Set<StudentMarksDetails> marksDetails) {
  this.marksDetails = marksDetails;
 }


 
}

StudentMarksDetails.java
package com.tutorialsdesk.hibernate.bean;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "STUDENT_MARKS_DETAILS")
public class StudentMarksDetails {

 @Id
 @GeneratedValue
 @Column(name = "test_id")
 private long testId;

 @Column(name = "subject")
 private String subject;

 @Column(name = "max_marks")
 private String maxMarks;

 @Column(name = "marks_obtained")
 private String marksObtained;

 @Column(name = "result")
 private String result;

 @ManyToOne
 @JoinColumn(name = "student_id")
 private Student student;

 public StudentMarksDetails() {
 }

 public StudentMarksDetails(String subject, String maxMarks, String marksObtained,
   String result) {
  this.subject = subject;
  this.maxMarks = maxMarks;
  this.marksObtained = marksObtained;
  this.result = result;
 }

 public long getTestId() {
  return testId;
 }

 public void setTestId(long testId) {
  this.testId = testId;
 }

 public String getSubject() {
  return subject;
 }

 public void setSubject(String subject) {
  this.subject = subject;
 }

 public String getMaxMarks() {
  return maxMarks;
 }

 public void setMaxMarks(String maxMarks) {
  this.maxMarks = maxMarks;
 }

 public String getMarksObtained() {
  return marksObtained;
 }

 public void setMarksObtained(String marksObtained) {
  this.marksObtained = marksObtained;
 }

 public String getResult() {
  return result;
 }

 public void setResult(String result) {
  this.result = result;
 }

 public Student getStudent() {
  return student;
 }

 public void setStudent(Student student) {
  this.student = student;
 }

}

Adding Hibernate Configuration file

The hibernate.cfg.xml is as follows:
<?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>
        <property name="hibernate.connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
        <property name="hibernate.connection.password">password</property>
        <property name="hibernate.connection.url">jdbc:jtds:sqlserver://localhost:1433/yourdbname</property>
        <property name="hibernate.connection.username">username</property>
        <property name="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</property>
     <property name="connection.pool_size">1</property>
        <property name="hbm2ddl.auto">create</property>
        <property name="show_sql">true</property>  
  <property name="format_sql">true</property>  
        <mapping class="com.tutorialsdesk.hibernate.bean.Student"/>
        <mapping class="com.tutorialsdesk.hibernate.bean.StudentMarksDetails"/>
       <!--  <mapping class="com.tutorialsdesk.hibernate.bean.StudentAddress"/>  -->
    </session-factory>
</hibernate-configuration>

In the above file we have set the database connection to SQL Server database . The show_sql option, if set to true will display all the executed SQL queries on the console. The property hbm2ddl.auto , if set to create, creates the schema, destroying the previous data.

Note : In case you want to use any other database then, you need to change these properties – “dialect”, “connection.driver_class”, “connection.url”, “connection.username”, and “connection.password”.

Also we have added the Annotation based entity classes Student.java and StudentMarksDetails.java to the above file.

Create Utility class

Next, we will write a utility class to take care of Hibernate start up and retrieve the session easily. We will write the file HibernateUtil.java as below:
package com.tutorialsdesk.hibernate;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration; 

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

  private static SessionFactory buildSessionFactory() {
   try {
    return new AnnotationConfiguration().configure().buildSessionFactory(); 
   } catch (Throwable ex) {
    System.err.println("Initial SessionFactory creation failed." + ex);
    throw new ExceptionInInitializerError(ex);
   }
  }

  public static SessionFactory getSessionFactory() {
   return sessionFactory;
  }

  public static void shutdown() {
   getSessionFactory().close();
  }


}


Main AnnotationTest class

This class tests the one-to-one relationship by creating and listing the student details and corresponding addresses as below:
package com.tutorialsdesk.hibernate;

import java.util.ArrayList;
import java.util.Set;

import org.hibernate.*;

import com.tutorialsdesk.hibernate.bean.Student;
import com.tutorialsdesk.hibernate.bean.StudentAddress;
import com.tutorialsdesk.hibernate.bean.StudentMarksDetails;

public class AnnotationTest {
public static void main(String[] args) {
 
 AnnotationTest test=new AnnotationTest();
 StudentAddress sa1 = new StudentAddress("C-42","Noida","UP","IN");
 StudentAddress sa2 = new StudentAddress("D-61","Agra","UP","IN");
 Student s1=new Student("CS1","Ankit","Yadav","MCA",sa1);
 Student s2=new Student("CS2","Rahul","Jena","B.Tech",sa1);
   StudentMarksDetails marksDetails1 = new StudentMarksDetails("Maths", "100", "87","Passed");
   StudentMarksDetails marksDetails2 = new StudentMarksDetails("Science", "100", "90","Passed");
   StudentMarksDetails marksDetails3 = new StudentMarksDetails("English", "100", "85","Passed");
   StudentMarksDetails marksDetails4 = new StudentMarksDetails("Maths", "100", "87","Passed");
   StudentMarksDetails marksDetails5 = new StudentMarksDetails("Science", "100", "90","Passed");
   StudentMarksDetails marksDetails6 = new StudentMarksDetails("English", "100", "85","Passed");
 
   marksDetails1.setStudent(s1);
   marksDetails2.setStudent(s1);
   marksDetails3.setStudent(s1);
   marksDetails4.setStudent(s2);
   marksDetails5.setStudent(s2);
   marksDetails6.setStudent(s2);   
   
   
 sa1.setStudent(s1);
 //s1.setAddress(sa1); 
 
 sa2.setStudent(s2);
 //s2.setAddress(sa2); 

 
 test.saveStudent(s1);
 test.saveStudent(s2);
 
 test.saveMarks(marksDetails1);
 test.saveMarks(marksDetails2);
 test.saveMarks(marksDetails3);
 test.saveMarks(marksDetails4);
 test.saveMarks(marksDetails5);
 test.saveMarks(marksDetails6);
 
 test.getStudent();
 System.out.println("successfully saved");
 
}
public void saveStudent(Student student) {
   Session session = HibernateUtil.getSessionFactory().openSession();
   session.beginTransaction();

   session.save(student);

   session.getTransaction().commit();
   
  }
public void saveMarks(StudentMarksDetails marksDetails) {
   Session session = HibernateUtil.getSessionFactory().openSession();
   session.beginTransaction();

   session.save(marksDetails);

   session.getTransaction().commit();
   
  }
  public void updateStudent(Student student) {
   Session session = HibernateUtil.getSessionFactory().openSession();
   session.beginTransaction();

   session.merge(student);

   session.getTransaction().commit();
  }

  public void deleteStudent(Student student) {
   Session session = HibernateUtil.getSessionFactory().openSession();
   session.beginTransaction();

   session.delete(student);

   session.getTransaction().commit();
  }

  public void getStudent() {
   Session session = HibernateUtil.getSessionFactory().openSession();
   session.beginTransaction();

   @SuppressWarnings("unchecked")
 ArrayList<Student> list = (ArrayList<Student>) session.createQuery("from Student").list();
   if (list != null) {
    for (int i = 0; i < list.size(); i++) {
     System.out.println("User ID : " + list.get(i).getId());
     System.out.println("User First Name : "+ list.get(i).getFirstname());
     System.out.println("User Last Name : "+ list.get(i).getLastname());
     System.out.println("User Roll No : " + list.get(i).getRollno());
     System.out.println("User Course : " + list.get(i).getCourse());
    // System.out.println("User Address : " + list.get(i).getAddress().getAddress() + ","+ list.get(i).getAddress().getCity() +"\n"+ list.get(i).getAddress().getState() +"\n"+ list.get(i).getAddress().getCountry());
    
   }
   }
   session.getTransaction().commit();
  }

}

Hibernate One-To-Many Mapping Using Java Annotations Tutorial with Examples

Hope we are able to explain you Hibernate One-To-Many Mapping Using Java Annotations, if you have any questions or suggestions please write to us using contact us form.(Second Menu from top left).

Please share us on social media if you like the tutorial.