Performance

Performance is a significant architectural concern. We showed how to enable statistics in Hibernate and collect various metrics via JMX in Chapter 7, Metrics and Statistics, to help you identify bottlenecks. Throughout this book, we have identified ways of improving performance. Let's revisit some of these concepts here and discuss how they are effective.

Lazy loading

The decision to use lazy loading depends on specific situations. It is important to understand how lazy loading is accomplished. As we discussed, when you load an entity, Hibernate creates and returns a proxy object, which is uninitialized. (This doesn't occur when you use the get method.) Only when you access one of the attributes of the loaded entity does, Hibernate submit a database query to fetch the values. The same concept applies to associated entities. When you fetch the parent entities, the lazy-loaded associated entities are not fetched until they are accessed. This causes an extra trip to the database. This is an improvement in performance when dealing with one or a few entities, especially when you are not certain if you need the associated entities. But, in cases when several entities are fetched along with their associated entities, lazy loading can create a bottleneck.

It is important to keep in mind that different association types have different default fetch types. For example, the default fetch type for one-to-one and many-to-one is FetchType.EAGER, whereas the default fetch type for one-to-many and many-to-many is FetchType.LAZY.

Fetch mode

We already discussed fetch mode in Chapter 4, Advanced Fetching. As you recall, when you set Fetch Mode to JOIN, Hibernate ignores the fetch type and uses the eager strategy. However, if you fetch the root entity using HQL, it will not pay attention to the fetch mode on the association. In that case, you would have to explicitly change the HQL to fetch the associated entity eagerly, as shown here:

persons = session
    .createQuery("from Person p left join fetch p.children")
    .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
    .list();

Batch processing

Hibernate delays writing the data until the session is closed and the transaction is committed. If you are processing a large number of database writes, consider flushing (and clearing) the session occasionally. Hibernate is smart enough to use the JDBC batch. Besides taking advantage of JDBC batch processing, this also reduces the memory footprint of such sessions. We already discussed this in Chapter 1, Entity and Session.

Caching

We dedicated an entire chapter of this book to Hibernate caching. It is important to understand this mechanism very well, particularly second-level caching; it could work in your favor, or it could be the source of problem. One effective way to determine if database caching is the root cause of your problems is to turn off caching (a simple configuration change).

Stateless session

Consider using a stateless session, as it performs better in some cases. You can achieve even better throughput if you split up the work using multiple threads. But, you have to ensure that your database allows enough simultaneous connections and ensure that you have enough connections in your application connection pool. The following is an example of using a stateless Hibernate session in a multithreaded mechanism, using 4 threads to store 200,000 entities:

List<Thread> threads = new ArrayList<Thread>();
for (int i = 0; i < 4; i++) {
  Thread thread = new Thread() {
    @Override
    public void run() {
      try {
      StatelessSession session = HibernateUtil
      .getSessionFactory()
      .openStatelessSession();
      Transaction transaction = session.beginTransaction();
    
      for (int i = 0; i < 50000; i++) {
          Person person = randomPersonNoChild();
          session.insert(person);
      }
      
      transaction.commit();
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  };
  threads.add(thread);
}

for (int i =0; i < threads.size(); i++) {
  threads.get(i).start();
}

Note

Note that it is not recommended to spawn threads in a Java Enterprise Application. For that, you should consider using asynchronous beans. Most enterprise application servers support asynchronous beans.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.17.140