Problem
When using getResultList() to retrieve the Rows of the DB table there may be times where you would end up getting the same rows multiple times.

Why this Happens
Let’s have a table tblGroup the one below

ParentGrp GrpName
Finance Accounts
Finance Sales
  1. You have 2 records in database.Both the records has Finance as value in parentGrp column
  2. Now when you run a select query to select parentGrp = ‘Finance’ you will get 2 records
  3. Lets query them WHERE parentGrp = ‘Finance’
  4. SQL Query returns 2 rows
  5. Hibernate loads first one, and puts into session, with parentGrp as a key.Now this will happen if you have specified it as @ID in entity class or you havent specified it while joining two tables in entity class.The object is placed into the result list.
  6. Hibernate loads second one, notices that an object with the same @Id is already in the session, and just places the reference into the result List. Row data are ignored.
  7. Now we have two copies of the same record

Solution:
We can solve this by introducing a primary key column something like tblGroup_pk_id.Now this helps to uniquely identify the records in the table so it won’t get overridden when the next rows retrieved.

Now the GrpId should be entitled with @ID annotation in the entity class.

GrpId ParentGrp GrpName
101 Finance Accounts
102 Finance Sales
createQuery() createSQLQuery() createCriteria()
Creates Query Object Creates Query Object Creates Criteria Object
Uses HQL Syntax Uses DB Specific Syntax Uses Entity Class
The Columns of the rows retrieved would be name of the POJO Model Class The Columns of the rows retrieved would be name of Native DB fields Create sql query using Criteria object for setting the query parameters
CRUD operation could be done CRUD operation could be done Only Read Operation is allowed
Supports Interoperability between different DB’s Does not support Interoperability since the query format should be changed when the DB is changed Supports Interoperability between different DB’s
Does not work without Model Class Bean with columns of Table alone is Enough.No need for Entity class generation Does not work without Model Class
No need for mapping between Entity class object and Table Columns The Bean Objects should be mapped with table Columns No need for mapping

createQuery – session.createQuery()

------------------------------------------------------
**DB_TBL_Col(tblEmployee)**| **POJO(Employee)**
EMP_ID                     | employeeID
------------------------------------------------------
Query query = session.createQuery("from Employee E where E.employeeID = 'A%'");
List<Person> persons = query.list();

Entity Manager is responsible for listener, entities, relationships, persist lifecycle of them and this interface defines the methods that are used to interact with the persistence context associated with an specific persistence context

TransactionManager is responsible for transactional data access, giving support to all the transaction that need to occurs within your application.

Transaction manager belongs with the Service layer, Entity Manager belong to the persistence layer

EntityManagerFactory and EntityManager are defined by the JPA standard. SessionFactory and Session are hibernate-specific. The EntityManager invokes the hibernate session under the hood

Why to prefer JPA API over the proprietary Hibernate?
The JPA API is cleaner than the Hibernate, Offers something that you can reuse in more other projects relying on a different implementation.

You can get the Hibernate Session from the JPA EntityManager

Session session = entityManager.unwrap(Session.class);

By using EntityManager, code is no longer tightly coupled with hibernate

JPA       - javax.persistence.EntityManager
Hibernate - org.hibernate.ejb.HibernateEntityManager

org.hibernate.AnnotationException: Use of @OneToMany or @ManyToMany targeting an unmapped class
Sol

  1. @Entity Should be added in the Model class
  2. If you have missed to add the Model class in the xml file
  3. Make sure the annotation is javax.persistence.Entity, and not org.hibernate.annotations.Entity. The former makes the entity detectable.

————————————————————————————————————————————————————-
javax.naming.NoInitialContextException: Need to specify class name in environment or system property
Sol
“I want to find the telephone number for John Smith, but I have no phonebook to look in”.This exception is thrown when no initial context implementation can be created.JNDI (javax.naming) is all about looking up objects or resources from some directory or provider. To look something up, you need somewhere to look (this is the InitialContext).

————————————————————————————————————————————————————-
hibernate exception: org.hibernate.AnnotationException: No identifier specified for entity
Sol

  1. You are missing a field annotated with @Id. Each @Entity needs an @Id – this is the primary key in the database.
  2. If you don’t want your entity to be persisted in a separate table, but rather be a part of other entities, you can use @Embeddable instead of @Entity.
  3. If you want simply a data transfer object to hold some data from the hibernate entity, use no annotations on it whatsoever – leave it a simple pojo.

————————————————————————————————————————————————————-
org.hibernate.hql.internal.ast.QuerySyntaxException: table is not mapped
Sol
In the HQL , you should use the java class name and property name of the mapped @Entity instead of the actual table name and column name

For example if your bean class name is UserDetails then the Hibernate code should be as below.Not Tbl_UserDetails instead of UserDetails

 Query query = entityManager. createQuery("Select UserName from UserDetails"); 

The problem can also be because of wrong import

import javax.persistence.Entity;

instead of

import org.hibernate.annotations.Entity;

————————————————————————————————————————————————————-

Hibernate works better if your view is more object-centric. If however you view is more database-centric then Ibatis is a much stronger choice.

Hibernate is object-relation mapping framework (ORM) which maps Java classes to database tables. MyBatis is persistence framework – not ORM. It maps SQL statements to Java methods.

Hibernate has first level cache which is impossible to disable. It means that if you query item through ORM and then delete it directly with SQL, it stays in the cache. You can explicitly clear the cache to get the most updated results from database but unfortunately such behavior may bring errors like “detached entity passed to persist”

If you perform Create/Update/Delete of some complex domain entities Hibernate works well allowing you to just make a POJO and persist/update it. It also does this quickly, unless your domain is quite large.

Run analytic fetch queries (i.e. summation/aggregation queries). IBatis is great for fetch queries where you just want an answer.Hibernate would attempt to load the entire object graph and you’d need to start tuning queries with LazyLoading tricks to keep it working on a large domain. Conversely if you just want some analytic POJO page, the myBatis implementation of the same query would be trivial.

CreationScript.java

	sessionFactory = createSessionFactory();
	Session objSession = sessionFactory.openSession();
	objSession.beginTransaction();

	Criteria crt = objSession.createCriteria(Users.class);
	crt.add(Restrictions.eq("UserName", "UserName 9"));


	List<Users> arrUsers = (List<Users>)crt.list();

	for (Users users : arrUsers) {
		System.out.println(users.getUserName());
	}

AND Restrictions

Criteria crt = objSession.createCriteria(Users.class);
	crt.add(Restrictions.eq("UserName", "UserName 9")).
		add(Restrictions.gt("UserId", 5));
Criteria crt = objSession.createCriteria(Users.class);
	crt.add(Restrictions.eq("UserName", "UserName 9")).
		add(Restrictions.gt("UserId", 5));
Criteria crt = objSession.createCriteria(Users.class);
		crt.add(Restrictions.eq("UserName", "UserName 9")).
			add(Restrictions.between("UserId", 5, 10));
Criteria crt = objSession.createCriteria(Users.class);
		crt.add(Restrictions.eq("UserName", "UserName 9")).
			add(Restrictions.between("UserId", 5, 10));

OR Restrictions

Criteria crt = objSession.createCriteria(Users.class);
		crt.add(Restrictions.or(Restrictions.between("UserId", 0, 5), Restrictions.like("UserName", "Updated %")));

Getting list of Users from users Table

     sessionFactory = createSessionFactory();
     Session objSession = sessionFactory.openSession();
     objSession.beginTransaction();
		
     Query objQuery = objSession.createQuery("from Users");
     List<Users> arrUsers = objQuery.list();
		
     objSession.getTransaction().commit();
     objSession.close();
		
     System.out.println(arrUsers.size());

     for (Users users : arrUsers) {
	System.out.println(users.getUserName());
     }

Pagination Using HQL

    Query objQuery = objSession.createQuery("from Users");		
    objQuery.setFirstResult(5);
    objQuery.setMaxResults(2);
    List<Users> arrUsers = objQuery.list();
				
    objSession.getTransaction().commit();
    objSession.close();
		
    System.out.println(arrUsers.size());
		
    for (Users users : arrUsers) {
	System.out.println(users.getUserName());
    }

Note: In Pagination the Starting record is specified by setFirstResult and ending record is specified by setMaxResults.

Taking a Specific Column for Entity

	Query objQuery = objSession.createQuery("select UserName from Users");		
	objQuery.setFirstResult(5);
	objQuery.setMaxResults(2);
	List<String> arrUsers = (List<String>)objQuery.list();

	objSession.getTransaction().commit();
	objSession.close();

	System.out.println(arrUsers.size());

	for (String users : arrUsers) {
		System.out.println(users);
	}

Note :
The Object Name in entity should be same as specified in class including Case. username will not work in select query but UserName does.

Parameter Binding in Hibernate
Method 1

  Query objQuery = objSession.createQuery("from Users where UserId >?");
  objQuery.setParameter(0, 5);		
  List<Users> arrUsers = (List<Users>)objQuery.list();

  for (Users users : arrUsers) {
	System.out.println(users.getUserName());
  }

Method 2

     Query objQuery = objSession.createQuery("from Users where UserId > :limit");
     objQuery.setInteger("limit", 5);
		
     List<Users> arrUsers = (List<Users>)objQuery.list();
				
     objSession.getTransaction().commit();
     objSession.close();
	
     for (Users users : arrUsers) {
	System.out.println(users.getUserName());
     }

NamedQuery vs NamedNativeQuery
NamedQuery helps to consolidate all query at particular place.

users.java

@Entity
@NamedQuery(name="Users.byUserId", query="from Users where UserId=?")
public class Users {
	@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
	private int UserId;
	private String UserName;
	
	public int getUserId() {
		return UserId;
	}
	public void setUserId(int userId) {
		UserId = userId;
	}
	public String getUserName() {
		return UserName;
	}
	public void setUserName(String userName) {
		UserName = userName;
	}	
}

CreationScript.java

	sessionFactory = createSessionFactory();
	Session objSession = sessionFactory.openSession();
	objSession.beginTransaction();
		
	Query objQuery = objSession.getNamedQuery("Users.byUserId");
        objQuery.setInteger(0, 5);
		
	List<Users> arrUsers = (List<Users>)objQuery.list();
	
	for (Users users : arrUsers) {
	   System.out.println(users.getUserName());
	}

NativeQueries helps us to query the table directly by using table name instead of querying through Entity like one in NamedQuery.This is useful when we use stored procedure to take our resultSets.

users.java

@Entity
@NamedNativeQuery(name="Users.byUserId", query="SELECT * from Users where UserId=?", resultClass=Users.class)
public class Users {
	@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
	private int UserId;
	private String UserName;
	
	public int getUserId() {
		return UserId;
	}
	public void setUserId(int userId) {
		UserId = userId;
	}
	public String getUserName() {
		return UserName;
	}
	public void setUserName(String userName) {
		UserName = userName;
	}	
} 

Note: resultClass=Users.class should be specified or else object class cast exception would be thrown.

There may be times where you want to retrieve data from DB, do some changes in it and save back the data.In such a time the connection could not be kept open for the whole period of time since db connections are resource intensive.

So I will fetch the object -> close the Session -> Do some operations -> Open new session again -> Update the Object -> Close the Session.

	sessionFactory = createSessionFactory();
	Session objSession = sessionFactory.openSession();
	objSession.beginTransaction();		
	Users objUser = objSession.get(com.mugil.user.Users.class, 11);
	objSession.getTransaction().commit();
	objSession.close();

	objUser.setUserName("Updated");

	objSession = sessionFactory.openSession();
	objSession.beginTransaction();
	objSession.update(objUser);
	objSession.getTransaction().commit();
	objSession.close();

Now the way Hibernate works is it first runs the select query for the value which should be changed and updates the value.So 2 queries for the whole process.Now there are chance’s the value fetched from DB may or may not be changed.So we can do a check which checks the fetched and updated value for uniquess before running the update query.If the fetched data is not changed th update query wont be run.

The Annotation for that is as below.

 @Entity
 @org.hibernate.annotations.Entity(selectBeforeUpdate=true)