-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Handling problems with EntityManagers and Hibernate-Search
PostPosted: Thu Jan 03, 2013 9:14 am 
Newbie

Joined: Thu Jan 03, 2013 7:18 am
Posts: 1
Hi all,

We are running a web application to manage the user's own publications. The most important function of the application is the search. The user starts typing and if he's finished a query will be executed. The data is stored in a PostgreSQL database version 8.4. We are using the following frameworks:

    hibernate 4.1.7.final with hibernate-entitymanager-4.1.7.final
    hibernate-search-4.1.1.final
    spring 3.1.1.release for dependency injection and transaction managment
    OpenEntityManagerInViewFilter
    Vaadin for GUI

The problem now is that we're running out of jdbc connections. Every time the user executes a search, three connections (we have three tabs with different search results) will be used and won't get released. After spending hours of debugging we detected that the EntityManagers from the main search method won't get closed. This makes sense because nowhere in the code these EntityManagers will be closed. If we close them on our own, we will get LazyInitializationExceptions when we try to show the search results because of the lazy loading of the dao's. So my questions are:
    Do we have to create an EntityManager from the EntityManagerFactory every time a search has been executed? (The way it is already implemented, see bellow)
    Or do we have to use the injected EntityManager? (As result we get LazyInitializationExceptions)
    Why do we get LazyInitializationExceptions when we're using OpenEntityManagerInViewFilter?

In the class GenericJpaDaoImpl.java we provide the basic dao methods:
Code:
public class GenericJpaDaoImpl implements GenericDao, Serializable {

   private static final long serialVersionUID = -1066085513967422846L;
   
   private EntityManager entityManager;


   @Transactional
   public <T> void persist(T entity) {
      entityManager.persist(entity);
   }

   @Transactional
   public <T> T merge(T entity) {
      return entityManager.merge(entity);
   }

   @Transactional
   public <T> void remove(T entity) {
      if (!entityManager.contains(entity)) {
         entity = entityManager.merge(entity);
      }
      entityManager.remove(entity);
   }

   @Transactional
   public <T> void removeAll(Class<T> entityClass) {
      List<T> all = findAll(entityClass);
      for (T entity : all) {
         remove(entity);
      }
   }

        public <T> List<T> findAll(Class<T> entityClass) {
      CriteriaQuery<T> query = entityManager.getCriteriaBuilder()
            .createQuery(entityClass);
      query.from(entityClass);
      List<T> results = entityManager.createQuery(query).getResultList();
      return results;
   }

       public <T> T findById(Class<T> entityClass, Integer id) {
      T result = entityManager.find(entityClass, id);
      entityManager.refresh(result);
      return result;
   }

   @SuppressWarnings("rawtypes")
   public List findByNativeQuery(String sqlString,
                                  Map<String, ?> params, int maxResults) {
      Query query = entityManager.createNativeQuery(sqlString);
      query.setMaxResults(maxResults);
      return parametrizeQuery(params, query);
   }

        public <T> List<T> findByNamedQueryAndNamedParam(Class<T> entityClass,
         String queryName, Map<String, ?> params) {
      Query query = entityManager.createNamedQuery(queryName, entityClass);
      return parametrizeQuery(params, query);
   }

        public <T> List<T> findByNamedParam(Class<T> entityClass,
         String queryString, Map<String, ?> params) {
      Query query = entityManager.createQuery(queryString, entityClass);
      return parametrizeQuery(params, query);

   }

   @Override
        public <T> List<T> findByNamedParam(Class<T> entityClass,
         String queryString, Map<String, ?> params, int firstResult,
         int maxResults) {
      Query query = entityManager.createQuery(queryString, entityClass);
      query.setFirstResult(firstResult);
      query.setMaxResults(maxResults);
      return parametrizeQuery(params, query);
   }

   public EntityManager getEntityManager() {
      return entityManager;
   }

   @PersistenceContext
   public void setEntityManager(EntityManager entityManager) {
      this.entityManager = entityManager;
   }
}


The class SearchServiceImpl.java executes the query from the user. The method query creates a new EntityManager every time a search will be executed. These EntityManagers won't get closed and as a result we're running out of connections. If we close them before the method returns, we get some LazyInitializationExceptions when we try to show the search result.
Code:
public class SearchServiceImpl {
   private static final Log log = LogFactory.getLog(SearchServiceImpl.class);
   
   private GenericDao dao;
   private EntityManagerFactory emf;

   public <T> QueryResult<T> query(Class<T> type,
         Query query, String sortField, boolean reverseSort, int pageSize, int startRow) {
      QueryResult<T> result = new QueryResult<T>();
      try {
         FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search
               .getFullTextEntityManager(emf.createEntityManager());
         FullTextQuery persistenceQuery = fullTextEntityManager
               .createFullTextQuery(query, type);
         if (!StringUtils.isEmpty(sortField)) {
            Sort sort = new Sort(new SortField(
                  sortField, SortField.STRING,
                  !reverseSort));
            persistenceQuery.setSort(sort);
         }

         if (pageSize > 0) {
            persistenceQuery.setMaxResults(pageSize);
            persistenceQuery.setFirstResult(startRow);
         }

         result.setResults(persistenceQuery.getResultList());
         result.setTotalResultCount(persistenceQuery.getResultSize());
      } catch (Exception e) {
         log.error("Exception occured during executing the query", e);
      }

      return result;
   }

   public void setDao(GenericDao dao) {
      this.dao = dao;
   }

   public void setEmf(EntityManagerFactory emf) {
      this.emf = emf;
   }

}


Additional information:

persistence.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
      http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
   version="1.0">
   <persistence-unit name="biblio" transaction-type="RESOURCE_LOCAL">
      <class>...</class>
      //Some classes
      <properties>
         <property name="hibernate.search.default.directory_provider" value="org.hibernate.search.store.impl.FSDirectoryProvider" />
                        <property name="hibernate.search.default.worker.thread_pool.size" value="5  " />
                        <property name="hibernate.search.default.worker.buffer_queue.max" value="30" />
                        <property name="hibernate.connection.release_mode" value="after_transaction" />
                        <property name="hibernate.ejb.discard_pc_on_close" value="true"/>
                        <property name="hibernate.show_sql" value = "false" />
                </properties>
   </persistence-unit>
</persistence>


applicationContext.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
      http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">

        <!-- some service stuff -->

        <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
        <!-- ==================================== Transaction Manager ==================================-->
        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
           <property name="persistenceXmlLocation" value="${persistence.path}" />
            <property name="dataSource" ref="dataSource"/>
            <property name="jpaVendorAdapter">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                    <property name="showSql" value="false"/>
                    <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQL82Dialect"/>
                </bean>
            </property>
            <property name="jpaDialect" ref="jpaDialect" />
            <property name="jpaProperties">
                <props>
                    <prop key="hibernate.search.default.indexBase">${hibernate.search.default.indexBase}</prop>
                    <prop key="hibernate.search.default.exclusive_index_use">false</prop>
                    <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                </props>
            </property>
        </bean>
        <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
        <!-- ==================================== Transaction Manager ==================================
        -->
        <bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
            <property name="entityManagerFactory" ref="entityManagerFactory"/>
            <property name="jpaDialect" ref="jpaDialect" />
        </bean>
        <tx:annotation-driven transaction-manager="txManager"/>
</beans>


I'm really appreciate for every kind of help. If you need more information please let me know.


Top
 Profile  
 
 Post subject: Re: Handling problems with EntityManagers and Hibernate-Search
PostPosted: Thu Jan 03, 2013 9:39 pm 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
I'm not too familiar with Spring and Vaadin, but here is my guess of what is happening, hoping it helps.

Incoming request: the OpenEntityManagerInViewFilter filter opens an EntityManager instance, let's call this instance "1"
Your Search method is invoked: you open EntityManager instance "2"
Page gets rendered -- some lazy loading is normally triggered at this stage.
End of request: OpenEntityManagerInViewFilter closes instance "1"

As you can see nobody is closing entityManager "2".

Now if you try to close your instance yourself:

Incoming request: the OpenEntityManagerInViewFilter filter opens an EntityManager instance, let's call this instance "1"
Your Search method is invoked: you open EntityManager instance "2"
You close EM instance "2"
Page gets rendered -- some lazy loading is triggered, but the entities are managed by EM "2" (NOT 1) so you get LazyInitExceptions

IMO the solution is that you should not create a new EntityManager but you should use the same EntityManager instance created by the filter.
This is a good idea anyway: there is no reason to create multiple EntityManagers, and having only one makes sure you won't be reloading the same data multiple times from the database.

Generally speaking, having multiple EntityManager instances around in the same context is a bad idea as it gets confusing; the exception is obsiouly when needed, like when loading different types from different databases.

_________________
Sanne
http://in.relation.to/


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.