Skip to main content

Best Practices in Hibernate with Java



Session Management with Hibernate



he best practice is in most cases session-per-request. That is, open a session in the beginning of handling a request, and close it in the end. You can do that in a Servlet Filter, for example.
Having one session for the entire application is bad, because it will accumulate a lot of entities in its 1st level cache, which is a memory leak. It may also produce undeterministic results when multiple clients use it at the same time

Its always better to open a new session for every request, and close the session once the request is processed. Like
Session session = HibernateUtil.getSessionFactory().openSession();
instead of
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
If we use the getCurrentSession() method , tansaction.commit() / rollback() closes the connection.
Avoid many-to-many association

“Many to many” usage is discouraged when a simple bidirectional “many-to-one”/“one-to-many” will do the job. In particular, a many-to-many association might always be represented as too many-to-one associations to an intervening class. This model is usually easy to extend. In a real system, you might not have a many-to-many association as there is almost always other information that must be attached to each link between associated instances, such as the date and time when an item was added to a category. The best way to represent this information is via an intermediate association class. On top of this, changing the definition of a primary key and all foreign keys that refer to it is a frustrating task.


Persistent class method’s equals() and hashCode() must access its fields through getter methods
This rule is important: the object instance that is passed as ‘other’ might actually be a proxy object and not the actual instance that holds the persistent state. This is the case where there are lazy associations between classes. This is one area where Hibernate is not completely transparent. But it is good practice to use accessor methods instead of direct instance variable access. When we are tuning the performance of the application, a lazy association might actually be required.
This potential issue raises a ClassCastException and can cause the application to become unstable.

Avoid non serializable Entities
When Entity bean instance is to be passed by value as a detached object (for example, through a remote interface), the entity class must implement the Serializable interface.Also, in some cases an OptimisticLockException will be thrown and wrapped by another exception, such as a RemoteException, when VM boundaries are crossed. Entities that might be referenced in wrapped exceptions should be Serializable so that marshaling will not fail. One of the consequences to not following this rule is receiving an exception when a non Serializable Entity is passed by value.
Avoid using references to the ID in the persistent class’ method equals()
In our analysis, this rule had the second lowest success ratio (37.13 percent). It is possible for the programmer to define the meaning of Java Equality. However, Hibernate will only set the ID field when saving the object; it is therefore important not to use the ID field in the Java Equality definition when it is a surrogate key. For that reason, saving the object that has been added to a set collection results in identity change. In addition, the behavior of the Set/Map collection class is not specified when the value of an object is changed in a manner that impacts equals comparisons while the object is an element in the Set or is the key of a Map, you might corrupt your database.
For example:
Employee e = new Employee();
Set set = new HashSet();
set.add(e);
System.out.println(set.contains(e));
p.setId(new Long(5));
System.out.println(set.contains(e));
Prints: false

Never use array to map a collection
The details of an array mapping are virtually identical to those of a list. However, we strongly recommend against the use of arrays, since arrays can’t be lazily initialized (there is no way to proxy an array at the virtual machine level). Lists, maps, and sets are the most efficient collection types.
So, using array can affect your application performance when it contains many items: lazy loading, optimized dirty checking, and poor performance features for persistent collections.


Avoid public/protected setter for the generated identifier field
A primary key value must never change once it has been assigned. Since it is a generated key, it is automatically set by Hibernate, or by another JPA implementation or by another provider. The actual behavior of an application tries to modify the value of a primary key that is not defined.

Best Practices for Joins and Queries

ü  Don't use joins unless really needed. They won't allow you to use neither lazy loading, nor using 2nd level cache for associations
ü  Use lazy="extra" for large collections, it won't retrieve all the elements until you ask it, you can also use size() method for instance without getting elements from DB
ü  Use load() method if it's possible since it doesn't issue a select query until it's required. E.g. if you have a Book and an Author and you want to associate them together, this will won't issue any selects, only single insert:
Book b = (Book) session.load(Book.class, bookId);
Author a = (Author) session.load(Author.class, authorId);
b.setAuthor(a);
session.save(b);

ü  Use named queries (in your hbm files or in @NamedQuery) so that they are not parsed during each query. Don't use Criteria API until it's required (it makes impossible to use PreparedStatement cache in this case)
ü  Use read-only modes for selects-only: session.setReadOnly(object, true). This will make Hibernate not to keep an original snapshot of the selected entity in the persistent context for further dirty checks.
ü  User 2nd level cache and Query Cache for read-mostly and read-only data.
ü  Use FlushMode.COMMIT instead of AUTO so that Hibernate doesn't issue select before updates, but be ready that this may lead to stale data being written (though Optimistic Locking can help you out).
ü  Take a look at batch fetching (batch-size) in order to select several entities/collections at one time instead of issuing separate queries for each one.
ü  Do queries like 'select new Entity(id, someField) from Entity' in order to retrieve only required fields. Take a look at result transformers.
ü  Use batch operations (like delete) if needed
ü  If you use native queries, specify explicitly what cache regions should be invalidated (by default - all).
ü  Take a look at materialized path and nested sets for tree-like structures.
ü  Set c3p0.max_statements in order to enable PreparedStatment cache in the pool and enable the statement cache of your DB if it's switched off by default.
ü  Use StatelessSession if it's possible, it overcomes dirty checks, cascading, interceptors, etc.
ü  Do not use pagination (setMaxResults()setFirstResult()) along with queries that contain joins to collections, this will result in all the records pulled from database and pagination will happen in memory by Hibernate. If you want pagination, ideally you shouldn't use joins. If you can't escape it, again - use batch fetching.


Comments

Popular posts from this blog

Conversion from Clob To String in java and Vice versa

/***reading Clob data from oracle table and setting to Pojo**/
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import oracle.sql.CLOB;

import com.poc.one.pojo.StagedMessage;

public class MessageDao {
private static String url = "jdbc:oracle:thin:@172.22.22.198:1521:ORACLE";
private static String username = "ABC123";
private static String password = "ABC123";


public  List readClobToBO() throws Exception {

Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn = DriverManager.getConnection(url, username, password);
PreparedStatement stmt = conn
.prepareStatement("SELECT ID, STORE_ID, MESSAGE_DATA FROM STAGED_MESSAGE ");
ResultSet resultSet = stmt.executeQuery();
List msgList= new ArrayList();

while (resultSet.next()) {

StagedMessage message = new StagedMessage();

message.setId(resultSet.getInt(1));
message.setStoreId(r…

Portable Java 8/ JDK8 setup without admin rights

Some time we got machine to work where we don't have access rights to install anything or if you do not want to install. You can get latest jdk running by this trick. Just follow step step & do comment if you like it.

Step by Step details to get running java from .exe setup without any admin rights. Get portable 7 zip from portableapps.comdownload java 8 from oracle  http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.htmlopen 7 zip & extract jdk-8u102-windows-x64.exeyou will see below folders                .data                .pdata                .rdata                .reloc                .rsrc                .text                CERTIFICATE

          5.Go inside E:\jdk-8u102-windows-x64\.rsrc\1033\JAVA_CAB10you will find 111 file.

         6.extract it it some folder where you can find tools.zip again extract that to some folder say Java & copy it to very first folder of setup along with .data,.rsrc etc.
         7.Go to folder where you have co…

Multi Threading , Producer consumer problem in Java

Multi threading is topic which is always fascinating for java developer. I feel its more about practical the theory. So here i wanted to present sample examples which clear understanding for several multi threading concept.

In Theory basically thread which is light weight process.Thread shares mostly same memory space.
I said mostly because there is some space called thread local which is not common to threads & separate for each thread. We create thread whenever we wanted to use multicore of processor although that doesn't mean single core cant use it. In single core context switching works among different running thread.

for example suppose there is website which is showing latest price as well as offer as well as doing order booking all these things can be assigned to different thread to provide parallel processing.



There are 2 ways for creating a thread.

Extend a thread & Implement a Runnable class. Extending a class is little avoided since it closed possibility for e…