views:

51

answers:

2

From what I've read so far I had the understanding that using transactions would be the solution to hibernate's lazy loading problems. The session would be available during the whole transaction in the service layer without further adue.

So maybe I misconfigured my transaction management? I'm actually a newb when it comes to spring and hibernate, but maybe you guys could help me out.

My configuration:

<bean class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
    id="sessionFactory">
    <property name="configLocation">
        <value>classpath:hibernate.cfg.xml</value>
    </property>
</bean>
<!-- Hibernate Template bean that will be assigned to DAOs. -->
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory">
        <ref bean="sessionFactory" />
    </property>
</bean>

<!--
    Transaction manager for a single Hibernate SessionFactory (alternative
    to JTA)
-->
<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
        <ref local="sessionFactory" />
    </property>
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

My DAO implementation would simply have a @Repository annotation and a Hibernate-template bean injected using autowiring.

A typical header of a service Implementation would be:

@Service
@Transactional(readOnly=true)
public class LeerlingServiceImpl implements LeerlingService {

    @Autowired
    LeerlingDAO leerlingDAO;
    @Autowired
    LeerplanDAO leerplanDAO;

With a @Service(readOnly=false) annotation if anything is actually saved/updated in that particular method.

Do I need to configure something else to make sure that I can load the right associations in my Service, or is this normally handled by transactions?

Right now I am just a bit confused of what I should actually do, so please help me:)

+1  A: 

Lazy-loading problems and transactions are not really related one to other. But that's another story :) You've done all well, apart from the access to session in your beans. No sure how you are going to do this. The standard solution (in spring 2.x, not sure about 3.x, haven't looked yet) is to use HibernateDaoSupport as base class for classes were you are going to have an access to session. But personally that looks a little dodgy to me, because adds dependency on Spring-specific classes. Better way is to inject session into your beans. To do this you need to declare your session bean with definition similar to that one:

<bean name="hibernateSession" class="org.springframework.orm.hibernate3.SessionFactoryUtils" factory-method="getSession"
  scope="prototype">
    <constructor-arg index="0" ref="hibernateSessionFactory"/>
    <constructor-arg index="1" value="false"/>
    <aop:scoped-proxy/>
</bean>

and then just use it.

Here are details:

http://stas-blogspot.blogspot.com/2009/10/hibernate-spring-in-standalone.html

Stas
Using a template is not the "standard" solution, it's just one option which is not really recommended since 2007. Just inject the `sessionFactory` and use `sessionFactory.getCurrentSession()` if you want to go template-less. See [So should you still use Spring's HibernateTemplate and/or JpaTemplate??](http://blog.springsource.com/2007/06/26/so-should-you-still-use-springs-hibernatetemplate-andor-jpatemplate/).
Pascal Thivent
That is a rather staggering amount of indirection just to get around calling sessionFactory.getCurrentSession(). Don't know what the performance consequences of inserting a getBean() into every single method invocation on a Session would be.
Affe
I've been using the extension of "hibernateDAOSupport" class in my DAO's (and injected it.). But how do I get my session to be available in my service and DAO or is this an unatural thing to do? Others recommend using: http://community.jboss.org/wiki/OpenSessioninView ;As this binds the session to the thread at each request.(so yes: I am making a webapp)
toomuchcs
@toomuchcs, the config you posted doesn't have any obvious problems. Maybe post some of the actual code that doesn't work? Expanding transaction scope isn't a magic bullet, there are still plenty of errors you could be making. OSIV is generally the blanket fix for lazy loading exceptions, but it does require the programmer to really understand how ORM works and what being attached to a session means, or you're going to end up with unexpected version number bumps and transient data ending up in your database.
Affe
@Pascal Thivent. Thank you for the link. My approach is almost the same as in described article, apart from necessity to manually call getCurrentSession to get the session. Agree, that is doesn't make difference :) I've called it "standard" just because Spring 2.x documentation references to it.
Stas
@Pascal Thivent. Also had a look at sources. SessionFactoryUtils does some stuff before, actually making a call to factory.getCurrentSession, like registering session with TransactionSyncronizationManager, etc. I wouldn't just throw it out.
Stas
A: 

I think my understanding of Spring was just bad till now; there was indeed no real management for our session management. Basically what now happened was: you could get data from the DAO, but right after you received it you couldn't even get lazy collections loaded because the session was closed.

Now we are using the hibernate interceptor, which attaches the session to the thread at the beginning of each request and closes it when it ends. This is not always the most ideal solution, but for a school project I wouldn't bother too much.

The other solution seems to be: add AOP in a way that @around is used that the session is only available during a service method call. I think this is the best solution, though, I'm not going to dig that deeply right now for this project. The good thing is that I know it exists.

This article also helped me a lot: http://www.jroller.com/kbaum/entry/orm_lazy_initialization_with_dao

To those interested: here is what I had to add: In Spring MVC 3.0 there is a new feature called mvc:intereceptors which made me type less xml.

<!-- WEB-INF/applicationContext.xml or your own XML config file -->
<mvc:interceptors>
    <bean
        class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
        <property name="sessionFactory">
            <ref local="sessionFactory" />
        </property>
    </bean>
</mvc:interceptors>
toomuchcs