Showing posts with label Hibernate. Show all posts
Showing posts with label Hibernate. Show all posts

Wednesday, 17 May 2017

Hibernate Lazy loading


Lazy loading loads the child objects on demand.

We have a parent and that parent has a collection of children. Using "lazy-load" concept, all children will not load while loading the parent. Instead, it loads them when requested to do so.

It is used to improve performance significantly since often you won't need the children and so they will not be loaded. Since Hibernate 3.0, lazy collection is enabled by default.

When Lazy Loading is needed: Sample Problem
Consider an online portal which maintains a catalog of products. This can be modeled as a catalog entity (Parent) managing a series of product entities (Children). In a large store, there may be tens of thousands of products grouped into various overlapping categories.

When a customer visits the store, the catalog must be loaded from the database. We probably don’t want the implementation to load every single one of the entities representing the tens of thousands of products to be loaded into memory. For a sufficiently large retailer, this might not even be possible, given the amount of physical memory available on the machine. Even if this were possible, it would probably cripple the performance of the site. Instead, we want only the catalog to load, possibly with the categories as well. Only when the user drills down into the categories should a subset of the products in that category be loaded from the database.

To manage this problem, Hibernate provides a facility called lazy loading. When enabled, an entity’s associated entities will be loaded only when they are directly requested.

How to Enable Lazy Loading in Hibernate
To enable lazy loading explicitly you must use "fetch = FetchType.LAZY" on an association which you want to lazy load when you are using hibernate annotations.

Lazy loading using Annotations
public class Category {

      @OneToMany(mappedBy = "category", fetch = FetchType.LAZY )
      private Set<ProductEntity> products;

      public Set<ProductEntity> getProducts() {
            return products;
      }
      public void setProducts(Set<ProductEntity> products) {
            this.products = products;
      }
}

Lazy loading using XML configuration
<set name="category" inverse="true" cascade="delete" lazy="false">
      <key column="category_id" />
            <one-to-many class="ProductEntity"/>
</set>

How Lazy Loading Works in Hibernate?
Hibernate uses a proxy object to support lazy loading. Basically, when you load data from tables, hibernate doesn’t load all the mapped objects. As soon as you reference a child or lookup object via getter methods, if the linked entity is not in the session cache, then the proxy code will go to the database and load the linked object. It uses javassist to effectively and dynamically generate sub-classed implementations of your entity objects.

Effect of Lazy Loading on Detached Entities
Hibernate can only access the database via a session, so if an entity is detached from the session and when we try to access an association (via a proxy or collection wrapper) that has not yet been loaded, Hibernate throws a org.hibernate.LazyInitializationException: could not initialize proxy - no Session in Hibernate.

The cure is to ensure either that the entity is made persistent again by attaching it to a session or that all of the fields that will be required are accessed (so they are loaded into entity) before the entity is detached from the session.

Important point
We should also aware about n+1-problem.

Hibernate will not actually load all children when you access the collection. Instead, it will load each child individually. When iterating over the collection, this causes a query for every child. In order to avoid this, you can trick hibernate into loading all children simultaneously, e.g. by calling parent.getChildren().size().



Thursday, 4 May 2017

Hibernate architecture

High-level view of the Hibernate architecture:

Minimal subset of Hibernate's APIs
The "minimal" architecture has the application provide its own JDBC connections and manage its own transactions.




Comprehensive architecture
The "comprehensive" architecture abstracts the application away from the underlying JDBC/JTA APIs and allows Hibernate to manage the details.


SessionFactory (org.hibernate.SessionFactory)
A threadsafe, immutable cache of compiled mappings for a single database. A factory for Session and a client of ConnectionProviderSessionFactory can hold an optional (second-level) cache of data that is reusable between transactions at a process, or cluster, level.

Session (org.hibernate.Session)
A single-threaded, short-lived object representing a conversation between the application and the persistent store. It wraps a JDBC connection and is a factory for TransactionSession holds a mandatory first-level cache of persistent objects that are used when navigating the object graph or looking up objects by identifier.

Persistent objects and collections
Short-lived, single threaded objects containing persistent state and business function. These can be ordinary JavaBeans/POJOs. They are associated with exactly one Session. Once the Session is closed, they will be detached and free to use in any application layer (for example, directly as data transfer objects to and from presentation).

Transient and detached objects and collections
Instances of persistent classes that is not currently associated with a Session. They may have been instantiated by the application and not yet persisted, or they may have been instantiated by a closed Session.

Transaction (org.hibernate.Transaction)
(Optional) A single-threaded, short-lived object used by the application to specify atomic units of work. It abstracts the application from the underlying JDBC, JTA or CORBA transaction. A Session might span several Transactions in some cases. However, transaction demarcation, either using the underlying API or Transaction, is never optional.

ConnectionProvider (org.hibernate.connection.ConnectionProvider)
(Optional) A factory for, and the pool of, JDBC connections. It abstracts the application from underlying Datasource or DriverManager. It is not exposed to the application, but it can be extended and/or implemented by the developer.

TransactionFactory (org.hibernate.TransactionFactory)
(Optional) A factory for Transaction instances. It is not exposed to the application, but it can be extended and/or implemented by the developer.


Friday, 3 March 2017

Nth maximum salary in MySQL using LIMIT clause

MySQL supports a LIMIT keyword, which provides pagination capability. We can find the nth highest salary in MySQL without using sub query.


SELECT salary FROM Employee ORDER BY salary DESC LIMIT N-1, 1;


4rth highest salary in MySQL with LIMIT clause: 
-- use database
use abusecore;

-- creating Employee table in mysql
CREATE TABLE Employee (name varchar(10), salary int);

-- inserting sample data into Employee table
INSERT INTO Employee VALUES ('Mill', 3000);
INSERT INTO Employee VALUES ('Sham', 4000);
INSERT INTO Employee VALUES ('Jack', 3000);
INSERT INTO Employee VALUES ('Pats', 5000);
INSERT INTO Employee VALUES ('Rock', 7000);

-- 4rth highest salary in MySQL
SELECT salary FROM Employee ORDER BY Salary DESC LIMIT 3,1

-- Output:
3000

Nth highest salary in MySQL with LIMIT clause:

SELECT salary FROM Employee ORDER BY Salary DESC LIMIT n-1,1;



This approach is faster than correlated query approach but its vendor dependent.

Wednesday, 11 January 2017

Significance of using Spring’s Hibernate Template



Spring's Hibernate Template (i.e. org.springframework.orm.hibernate.HibernateTemplate) is a helper class which provides utility methods for querying/retrieving data from the database. It also converts checked HibernateExceptions into unchecked DataAccessExceptions.

Benefits of HibernateTemplate:
  • HibernateTemplate, a Spring Template class simplifies interactions with Hibernate Session.
  •  Common functions are simplified to single method calls.
  •  Sessions are automatically closed.
  •  Exceptions are automatically caught and converted to runtime exceptions.


Tuesday, 10 January 2017

Hibernate named query examples


Scattered HQL string literals in Java code are hard to maintain and look ugly. To avoid it, Hibernate come out a technique called “names queries”, it lets developer to put all HQL into the XML mapping file or via annotation.

XML mapping file:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
      <class name="com.dto.EmployeeDTO"  table="EMPLOYEES">
            <id name="id" column="ID"><generator class="assigned"/></id>
            <property name="empId" column="EMP_ID" />
            <property name="empFirstName" column="EMP_FIRST_NAME" />
            <property name="empLastName" column="EMP_LAST_NAME" />
            <property name="createdOn" column="CREATED_ON"/>
      </class>

      <!-- Native SQL in named query -->
      <sql-query name="updateEmployee">
            <![CDATA[
                  UPDATE EMPLOYEES SET EMP_LAST_NAME=:empLastName WHERE EMP_ID=:employeeId
            ]]>
      </sql-query>

      <!-- HQL in named query -->
      <query name="findEmpById">
        <![CDATA[from EmployeeDTO e where e.empId = :employeeId]]>
    </query>
</hibernate-mapping>

HQL and Native SQL in annotation
<!-- HQL in named query -->
@NamedQueries({
     @NamedQuery(
                name = "updateEmployee",
                query = "from EmployeeDTO e where e.empId = :employeeId"
     )
})

<!-- Native SQL in named query -->
@NamedNativeQueries({
     @NamedNativeQuery(
                name = "updateEmployee",
                query = "UPDATE EMPLOYEES SET EMP_LAST_NAME=:empLastName WHERE EMP_ID=:employeeId",
                resultClass = EmployeeDTO.class
     )
})
@Entity
@Table(name = "EMPLOYEES")
public class EmployeeDTO implements java.io.Serializable {
     ...
}

Java Code to use the named Query:
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class HibernateNamedQuery extends HibernateDaoSupport {

      public int updateEmployee(String p_employeeId, String p_modifiedBy) {
            Session session = null;
            try {
                  session = getHibernateTemplate().getSessionFactory().openSession();
                  Query query = session.getNamedQuery("updateEmployee");
                 
                  query = query.setString("empLastName", "Kumar");
                 
                  int rowsUpdated = query.executeUpdate();
     
                  return rowsUpdated;
            } finally {
                  releaseSession(session);
            }
      }
     
      public List<Object[]> fetchEmployeeDetails(String empId) {
            Session session = null;
            try {
                  session = getHibernateTemplate().getSessionFactory().openSession();
                 
                  Query query = session.getNamedQuery("findEmpById");
                  query = query.setString("employeeId",empId);
                 
                  return query.list();
            } finally {
                  releaseSession(session);
            }
      }
}


Related Posts Plugin for WordPress, Blogger...