-->
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.  [ 5 posts ] 
Author Message
 Post subject: How to "reattach" Entity to a Hibernate Session?
PostPosted: Tue Feb 03, 2009 5:14 pm 
Beginner
Beginner

Joined: Tue Feb 03, 2009 4:33 pm
Posts: 21
I'm trying to make the switch to hibernate (using Spring config and HibernateTemplate), but I keep getting LazyInitializationExceptions all over the place.

Basically, I'm configuring hibernate thusly:
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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <description>Configuration file for avp-Dao (Hibernate config).</description>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName">
            <value>@@db.driver@@</value>
        </property>
        <property name="url">
            <value>@@db.url@@</value>
        </property>
        <property name="username">
            <value>@@db.user@@</value>
        </property>
        <property name="password">
            <value>@@db.password@@</value>
        </property>
    </bean>

    <bean id="openSessionInViewInterceptor" class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
        <!--<property name="flushModeName" value="FLUSH_AUTO"/>-->
        <property name="sessionFactory" ref="sessionFactory"/>
        <property name="singleSession" value="true"/>
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="mappingResources" ref="mappingResources"/>
        <!--  <property name="connectionReleaseMode"><value>???</value></property> -->
        <property name="hibernateProperties" ref="hibernateProperties"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--  Hibernate Properties -->
    <bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
        <property name="properties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.max_fetch_depth">3</prop>
                <!--<prop key="flushMode">AUTO</prop>-->
                <prop key="hibernate.hibernate.cache.use_query_cache">true</prop>
                <prop key="hibernate.jdbc.batch_size">50</prop>
                <!--<prop key="hibernate.connection.release_mode">auto</prop>-->
                <!--<prop key="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</prop>-->

                <!-- Connection Pool -->
                <prop key="hibernate.connection.pool_size">10</prop>
                <prop key="hibernate.c3p0.min_size">1</prop>
                <prop key="hibernate.c3p0.max_size">20</prop>
                <prop key="hibernate.c3p0.timeout">1800</prop>
                <prop key="hibernate.c3p0.max_statements">100</prop>

                <!-- Use EHCache as secondary cache-->
                <prop key="hibernate.cache.use_query_cache">true</prop>
                <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
                <prop key="hibernate.cache.provider_configuration_file_resource_path">com/foo/avp/repository/hibernate/ehcache.xml</prop>
            </props>
        </property>
    </bean>


    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
        <constructor-arg>
            <ref bean="sessionFactory"/>
        </constructor-arg>
        <!-- <property name="allowCreate" value="false"/> -->
        <!--<property name="flushModeName" value="FLUSH_AUTO"/>-->
    </bean>

    <bean id="hibernateTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <constructor-arg>
            <ref bean="sessionFactory"/>
        </constructor-arg>
    </bean>

    <!--  hibernate mapping files (in avp.hibernate JAR) -->
    <bean id="mappingResources" class="org.springframework.beans.factory.config.ListFactoryBean">
        <property name="sourceList">
            <list>
                <value>com/foo/avp/model/Category.hbm.xml</value>
                <value>com/foo/avp/model/CategoryProperty.hbm.xml</value>
                <value>com/foo/avp/model/Channel.hbm.xml</value>
                <value>com/foo/avp/model/ChannelGroup.hbm.xml</value>
                <value>com/foo/avp/model/ChannelProperty.hbm.xml</value>
                <value>com/foo/avp/model/Media.hbm.xml</value>
                <value>com/foo/avp/model/MediaFile.hbm.xml</value>
                <value>com/foo/avp/model/Role.hbm.xml</value>
                <value>com/foo/avp/model/RssAccount.hbm.xml</value>
                <value>com/foo/avp/model/User.hbm.xml</value>
                <value>com/foo/avp/model/UserChannelPermission.hbm.xml</value>
            </list>
        </property>
    </bean>

    <!-- Dao layer -->
    <bean id="categoryRepository" class="com.foo.avp.repository.hibernate.CategoryRepositoryImpl">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
        <property name="hibernateTemplate">
            <ref bean="hibernateTemplate"/>
        </property>
    </bean>

    <bean id="channelRepository" class="com.foo.avp.repository.hibernate.ChannelRepositoryImpl">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
        <property name="hibernateTemplate">
            <ref bean="hibernateTemplate"/>
        </property>
    </bean>

    <bean id="mediaRepository" class="com.foo.avp.repository.hibernate.MediaRepositoryImpl">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
        <property name="hibernateTemplate">
            <ref bean="hibernateTemplate"/>
        </property>
    </bean>

    <bean id="rssAccountRepository" class="com.foo.avp.repository.hibernate.RssAccountRepositoryImpl">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
        <property name="hibernateTemplate">
            <ref bean="hibernateTemplate"/>
        </property>
    </bean>

    <bean id="userRepository" class="com.foo.avp.repository.hibernate.UserRepositoryImpl">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
        <property name="hibernateTemplate">
            <ref bean="hibernateTemplate"/>
        </property>
    </bean>

    <bean id="userChannelPermissionRepository" class="com.foo.avp.repository.hibernate.UserChannelPermissionRepositoryImpl">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
        <property name="hibernateTemplate">
            <ref bean="hibernateTemplate"/>
        </property>
    </bean>

    <bean id="channelPropertyRepository" class="com.foo.avp.repository.hibernate.ChannelPropertyRepositoryImpl">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
        <property name="hibernateTemplate">
            <ref bean="hibernateTemplate"/>
        </property>
    </bean>

    <bean id="categoryPropertyRepository" class="com.foo.avp.repository.hibernate.CategoryPropertyRepositoryImpl">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
        <property name="hibernateTemplate">
            <ref bean="hibernateTemplate"/>
        </property>
    </bean>

    <bean id="roleRepository" class="com.foo.avp.repository.hibernate.RoleRepositoryImpl">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
        <property name="hibernateTemplate">
            <ref bean="hibernateTemplate"/>
        </property>
    </bean>

    <bean id="channelGroupRepository" class="com.foo.avp.repository.hibernate.ChannelGroupRepositoryImpl">
        <property name="sessionFactory">
            <ref bean="sessionFactory"/>
        </property>
        <property name="hibernateTemplate">
            <ref bean="hibernateTemplate"/>
        </property>
    </bean>

</beans>


That OSIV interceptor was a last desperate attempt to solve this issue, but doesn't appear to have any discernible effect.

The whole repository / DAO layer, as well as the entities it returns, is defined in a separate JAR. I don't want the client application to be aware of Hibernate, or any special transaction / session considerations, which the Spring HibernateTemplate is supposed to take care of.

Problem: Each ChannelGroup entity contains a child Set of Channel objects, which is lazy-initialized when the ChannelGroup is returned by the Dao. Within the client application, any time I attempt to access members of the Channel set, I receive
Code:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.foo.avp.model.ChannelGroup.channels, no session or session was closed


As I understand it, this is because, after returning the retrieved ChannelGroup entity, the HibernateTemplate (or whatever) closes the session. So basically the entity is disconnected from the session. This means I can't browse child collections or objects, can't update the entity, or perform any meaningful data-backed operation.

From my perusals on the internet, either no one in the history of the world has ever solved this problem, which begs the question: why the hell would anyone want to use Hibernate, or else everyone but me has solved this problem. In which case, I beg you to share your solution.

Is there a way to "re-attach" the entity to a hibernate session, to complete the lazy-init? Can this be done in a way that the client application doesn't need to know that I'm using Hibernate?

Is lazy-init useful at all?

And yes, I tried the n00b solution of setting all my entities to lazy="false". Of course Hibernate attempted to load the entire database into memory and ran out of Heap :-).


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 05, 2009 12:26 pm 
Beginner
Beginner

Joined: Tue Feb 03, 2009 4:33 pm
Posts: 21
Well, it turns out the OSIV interceptor was pretty useless, as I'm not using Spring MVC. I replaced it with an OSIV Filter in web.xml, which didn't work.

Really? Has no one in the history of the universe ever attempted to use Hibernate in a web application? I've posted this same question on five different forums, and no one has responded...

I guess I'll go back to plain Jdbc.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 05, 2009 3:43 pm 
Newbie

Joined: Thu Nov 15, 2007 3:17 am
Posts: 19
You have to configure Transactions for your DAO methods. The hibernate session is bound to the transaction scope so you are able to load lazy properties until the transaction will be comitted.

Take a look at the spring documentation about how to configure transactions for your DAO / service methods. It can be done either by xml configuration or by annotations.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 05, 2009 4:06 pm 
Beginner
Beginner

Joined: Tue Feb 03, 2009 4:33 pm
Posts: 21
Byto, God bless you for replying. So far you're the only one.

Right now, all my DAO methods are marked as @Transactional. Truth to tell, I don't really know what this does.

But let's say I have a Dao method called GetCustomerById. And each customer has a child collection of Orders. All of these DAO methods are called by a client application that doesn't want to know anything about Hibernate or SQL, or any of the messy details. When the client application calls GetCustomerById, the returned Customer object has it's Orders collection lazy-initialized. If, after calling the DAO method, I attempt to access the Orders collection, I will receive a LazyInitializationException.

If I mark the GetCustomerById method as @Transactional, that won't really help (If I understand correctly), since the transaction ends when the method returns. I would have to remove the @transactional annotation from the method, then start the transaction in the client code, access the child collection within the same transaction, do whatever it is I want to do, then be sure to commit the transaction when I'm done.

Unless I'm missing something (which is probable), this is completely the opposite of separation of concerns, since every layer of the application that needs to use these entities will have to be aware of the Transaction mechanism being used.

Not to mention, if the client aplication is itself being used by some other downstream system, like so:

(Hibernate) --> DAO --> BO / services --> Struts Action / Controller --> JSP Page

that system also has to manage transactions, and I have to remove any transaction handling from any upstream system. Not very modular.

Now it's probable that I've completely misunderstood all of this, but so far people are not exactly crashing the gates to set me straight. :-(

I've tried an OpenSessionInViewFilter, which on the surface appears to promise exactly what I'm looking for (start the session when the request comes in, close the session when the response is flushed), but in reality does pretty much nothing at all.


Top
 Profile  
 
 Post subject: Re: How to "reattach" Entity to a Hibernate Session?
PostPosted: Sun Aug 23, 2009 7:35 am 
Newbie

Joined: Sun Aug 23, 2009 7:17 am
Posts: 2
Hello guys..Use 'openSessionInViewInterceptor' to solve Lazy initialization.

<bean id="openSessionInViewInterceptor" class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
<property name="sessionFactory">
<ref bean="factory" />
</property>
<property name="singleSession" value="true"/>
<property name="flushModeName">
<value>FLUSH_AUTO</value>
</property>

</bean>

<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="openSessionInViewInterceptor"/> </list>
</property>
<property name="mappings">
<props>
<prop key="/login.do">logginController</prop>
<prop key="/contact.do">Contact</prop>
<prop key="/add.do">AddUser</prop>
</props>
</property>
</bean>


<bean id="factory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="mappingResources">
<list>
<value>history.hbm.xml</value>
<value>personnalHealth.hbm.xml</value>
<value>educationaExpl.hbm.xml</value>
<value>abroadExp.hbm.xml</value>
<value>workExp.hbm.xml</value>
<value>homeAssetsHist.hbm.xml</value>
<value>contactlist.hbm.xml</value>
<value>interests.hbm.xml</value>
<value>officeAssets.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName">
<value>org.hsqldb.jdbcDriver</value>
</property>
<property name="url">
<value>jdbc:hsqldb:hsql://localhost:8887</value>
</property>
<property name="username">
<value>sa</value>
</property>
<property name="password">
<value></value>
</property>
</bean>


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 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.