Showing posts with label hibernate. Show all posts
Showing posts with label hibernate. Show all posts

Wednesday, 6 August 2014

What's the difference between JPA and Hibernate?

The Java Persistence Architecture API (JPA) is a Java specification for accessing, persisting, and managing data between Java objects / classes and a relational database. 

Let's take a further look at this definition.  As the API portion of the name implies, JPA is a specification, meaning it provides guidelines for developing an interface that complies with a certain standard.  While JPA dictates an interface, it does not provide an implementation of that interface, meaning there is no underlying code that performs the operations to persist an object to a relational database.

It should also be noted the term Object Relational Mapping, is often used to describe the process of accessing, persisting and managing data between Java objects and a relational database.

To look at the concept of JPA from another perspective, imagine if you were provided this interface.

public interface JPA {
     
    public void insert(Object obj);
     
    public void update(Object obj);
     
    public void delete(Object obj);
     
    public Object select();
     
}

Without further development, what immediate value does this interface provide?  While this interface has potential to provide value, at this point, very little value is provided because the interface lacks an implementation.  If this interface is used within any code it will not execute because no concrete objects that implement this interface exist to perform the work.  This same concept applies to JPA just on a larger scale since the API specification defines many interfaces and annotations.

This is where the role of the JPA provider comes into play.  JPA providers develop a JPA implementation that meets the requirements of the JPA specification.  Hibernate is a JPA Provider, as well as others such as EclipseLink and TopLink.  With a JPA implementation in place Java objects can be now be persisted to a relational database, since there is underlying code to perform the work.

Returning to our interface analogy, if JPA is the interface then Hibernate represents a class that implements the interface.

public class Hibernate implements JPA {
 
    public void insert(Object obj) {
       //Persistence code
    }
 
    public void update(Object obj) {
       //Persistence code
         
    }
 
    public void delete(Object obj) {
      //Persistence code
         
    }
 
    public Object select() {
        //Persistence code
    }
     
    public Object superSelect(){
        //Persistence Code
    }
}

Notice that in addition to implementing the JPA interface, the Hibernate class contains some methods superfluous to the interface.  Keep this in mind for later.  Given this JPA implementation, we could now write some code that relies upon it to persist some data to a relational database.


public class MyApplication {
 
    public static JPA jpa = new Hibernate();
     
    public static void main(String[] args) {
        Object object = new Object();
        jpa.insert(object);  //writes to DB
    }
}

The new application works well initially, but after a couple of months its performance degrades.  Let's assume that the Hibernate implementation behind the scenes has several deficiencies causing  the poor performance.  Remember, this is for example purposes and I am not judging the merit of Hibernate.

Upon encountering this issue, another provider may decide the need for another JPA implementation exists.  This provider creates their own implementation of the JPA specification and publishes the code.

public class ToThoughtJpa implements JPA {
    //Implementation
}

Having used the JPA interface in our application, we can now easily make the switch to the more reliant JPA implementation.

public class MyApplication {
 
    public static JPA jpa = new ToThoughtJpa();
     
    public static void main(String[] args) {
        Object object = new Object();
        jpa.insert(object);  //writes to DB
    }
}

The concept illustrated in our simple example is the main value JPA provides only on a much larger scale.  If we choose to use JPA, we can eventually switch out our chosen JPA implementation for another implementation as long as they both meet the JPA specification.  In reality, this is not always a seamless transition, since we often utilize features of the implementation that are not support by the specification and each implementation has its own little quirks.  To illustrate this point, consider if we had called the superSelect method within our application.

public class MyApplication {
 
    public static Hibernate jpa = new Hibernate();
     
    public static void main(String[] args) {
        Object object = new Object();
        jpa.insert(object);  //writes to DB
        jpa.superSelect();
    }
}

Notice that in order to call the method, the interface of type JPA must be replaced with the Hibernate implementation.  At this point, we cannot swap our JPA implementation to the ToThoughtJpa JPA implementation because its interface does not contain the superSelect method.  This example attempts to illustrate the restrictions that occur when a developer chooses to use the straight Hibernate implementation, which is not bound by the JPA specification.

In summary, JPA is not an implementation, it will not provide any functionality within your application.  Its purpose is to provide a set of guidelines that can be followed by JPA providers to create an ORM implementation in a standardized manner.  This allows the underlying JPA implementation to be swapped and for developers to easily transition (think knowledge wise) from one implementation to another.  Hibernate is arguably the most popular JPA provider.  Hibernate's JPA implementation is used by many developers, however some choose to use the actual Hibernate implementation itself because the implementation may contain advanced functionality not contained in the JPA implementation.

Wednesday, 30 July 2014

Hibernate N+1 Problems And Solution

Hibernate N+1 SELECT’s Problems And Solution
Hibernate n+1 problems only comes for one to many relationship.
Let say one example – Retailer with a one-to-many relationship with Product. One Retailer has many Products.
***** Table: Retailer *****
+—–+——————-+
| ID | NAME |
+—–+——————-+
| 1 | Retailer Name 1 |
| 2 | Retailer Name 2 |
| 3 | Retailer Name 3 |
| 4 | Retailer Name 4 |
+—–+——————-+
***** Table: Product *****
+—–+———–+——————–+——-+————+
| ID | NAME | DESCRIPTION | PRICE | RETAILERID |
+—–+———–+——————–+——-+————+
|1 | Product 1 | Name for Product 1 | 82.0 | 4 |
|2 | Product 2 | Name for Product 2 | 20.0 | 2 |
|3 | Product 3 | Name for Product 3 | 10.0 | 2 |
|4 | Product 4 | Name for Product 4 | 77.0 | 3 |
+—–+———–+——————–+——-+————+
Factors:
Lazy mode for Retailer set to “true” (default)
Fetch mode used for querying on Product is Select
Fetch mode (default): Retailer information is accessed
Caching does not play a role for the first time the Retailer is accessed
Fetch mode is Select Fetch (default)

1
2
3
4
5
6
7
8
9
10
11
// It takes Select fetch mode as a default
Query query = session.createQuery( "from Product p");
List list = query.list();
// Retailer is being accessed
displayProductsListWithRetailerName(results);
 
// It takes Select fetch mode as a default
Query query = session.createQuery( "from Product p");
List list = query.list();
// Retailer is being accessed
displayProductsListWithRetailerName(results);


select * from PRODUCT
select * from RETAILER where RETAILER.id=?
select * from RETAILER where RETAILER.id=?
select * from RETAILER where RETAILER.id=?
Result:
1 select statement for Product
N select statements for RETAILER
This is N+1 select problem!

Solution to N+1 SELECTs problem

(i) HQL fetch join
“from RETAILER retailer join fetch retailer.product Product”
Corresponding SQL would be –
SELECT * FROM RETAILER retailer LEFT OUTER JOIN PRODUCT product ON product.product_id=retailer.product_id
(ii) Criteria query
Criteria criteria = session.createCriteria(Retailer.class);
criteria.setFetchMode(“product”, FetchMode.EAGER);
In both cases, the query returns a list of Retailer objects with the Product initialized. Only one query needs to be run to return all the Product and Retailer information required.

Monday, 21 July 2014

First Level and Second Level Cache in Hibernate

Hibernate is actually a very powerful, consistent, and reliable database mapping tool. Mapping between objects in Java to relational databases has many facets that you must be aware of. Hibernate does a particularly good job of making the process simple to start, and providing the facilities to allow it to scale well and meet exceedingly complex mapping demands. 

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:
 
 
 
One of the primary concerns of mappings between a database and our Java application is performance.  This is the common concern of the all guys who working with hibernate and spent the more time in ORM tools for performance-enhancing changes to particular queries and retrievals. Today I want to discuss about some facets of the Hibernate infrastructure that are implemented to handle certain performance concerns - 
  1. The first-level cache - Session (Earlier hibernate already provide this level of cache)
  2. The second-level cache -Session-factory-level cache
  3. and the query cache.
The first-level cache: The first level cache type is the session cache. The session cache caches object within the current session but this is not enough for long level i.e. session factory scope.
The second-level cache: The second-level cache is called 'second-level' because there is already a cache operating for you in Hibernate for the duration you have a session open. A Hibernate Session is a transaction-level cache of persistent data. It is possible to configure a SessionFactory-level cache on a class-by-class and collection-by-collection basis.
                 second-level cache
                     -- Across sessions in an Application
                     -- Across applications (different applications on same servers with same database)
                     -- Across clusters (different applications on different servers with same database)

NOTE: Be careful Caches are never aware of changes made to the persistent store by another application i.e. suppose one application deploy one server with using hibernate and get the data from database and put to the cache for further using purpose but another application deployed another server which does not using any ORM tool so it does mot know about Cache and direct interacting with database and may be update data of database. Now data in Cache is invalid.

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 'second-level' cache exists as long as the session factory is alive. The second-level cache holds on to the 'data' for all properties and associations (and collections if requested) for individual entities that are marked to be cached.