Announcement Announcement Module
Collapse
No announcement yet.
using getSession() instead of hibernateTemplate Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • using getSession() instead of hibernateTemplate

    Hi

    Am a beginner to Spring.

    I have an existing application in hibernate. There is a plan to implement Spring in the application and using spring-hibernate. This should happen with as much minimal changes as possible to the existing code.

    My current application structure is as follows:

    Current application has one Generic DAO which has all standard methods to retrieve and persist. And all the dao's extend this generic DAO and they will have custom methods which handles complex queries.

    We are passing session to the DAO's through constructor and using that session for executing the queries.

    1. Now If want to use Spring-Hibernate, using HibernateTemplate is the best, but I have to touch all the DAO's and each and every method in those DAO's to wrap the queries with hibernate template. Please suggest if you have some thing better, which we can be injected into the DAO's without touching the all the methods in the DAO.

    2. One solution that I have is, use getSession() of HibernateSupportDAO instead of hibernateTemplate(). And I'll be implementing transactions through Spring AOP. If so, will the session closing be handled by the transaction interceptor? Or Do I need to take care of closing the session in the code explicitly?

    Could any one please provide a suggestion?
    Thanks in Advance.

  • #2
    Neither. It isn't recommended to use either HibernateDaoSupport or HibernateTemplate any any more.

    Create a plain hibernate based dao and use the getCurrentSession method not openSession (important!!!!). That in combination with declarative transaction management is enough to get all the nice stuff from hibernate and from spring.

    I suggest you read the reference guide especially the hibernate chapter.

    Comment


    • #3
      Hi Marten,
      Could you please elaborate your suggestion....

      Comment


      • #4
        As I stated, read the chapter about hibernate that explains it all. You wan to read chapter 12.2.5.

        Comment


        • #5
          Thanks Martin.

          I read the reference guide and implemented with plain Hibernate DAO and Spring JTA. It is working.

          Thanks a lot.

          Comment


          • #6
            Originally posted by Marten Deinum View Post
            Neither. It isn't recommended to use either HibernateDaoSupport or HibernateTemplate any more.
            As I see there is an advantage using HibernateTemplate over plan Hibernate3 DAO: hibernate exceptions are automatically converted into DataAccessExceptions.

            Is it possible to achive this while using plain hibernate3 daos without HibernateTemplate?

            Comment


            • #7
              As I already suggested 2 times, read the reference guide, the link is there which explains it all.

              Originally posted by byto
              Is it possible to achive this while using plain hibernate3 daos without HibernateTemplate?
              Yes it is, else the template/daosupport would still be the way to go...

              Comment


              • #8
                Originally posted by Marten Deinum View Post
                Yes it is, else the template/daosupport would still be the way to go...
                So please tell me how I get the hibernate exceptions wrapped while using plain hibernate 3 daos!? After deleting HibernateTemplate from my DAOs and using getCurrentSession() instead, one of my unittests throws a hibernate related exception instead of wrapping it with DataIntegrityViolationException from Spring.

                Comment


                • #9
                  As I suggested 3 times already RTFM... Chapter 12.6.4 explains it all...

                  Comment


                  • #10
                    Cant get it work. I think its because Im using HibernateTransactionManager instead of JpaTransactionManager? IIRC the HibernateJpaDialect is used to translate hibernate exceptions to data access exceptions. But I dont see how I can set up one of those while using HibernateTransactionManager.

                    Comment


                    • #11
                      It has nothing to do with your transaction manager. The LocalSessionFactoryBean (or the annotatin one) implements the interface needed for the conversion. Make sure that they are defined in the same application context file and that you are also using an ApplicationContext instead of a BeanFactory...

                      Comment


                      • #12
                        Sorry it was my fault (misconfiguration). It works fine, now.
                        Thanks for your patience!!

                        Comment


                        • #13
                          using getSession() without HibernateDaoSupport

                          Martin, thanks for pointing out the HibernateDaoSupport is no longer the "best practice".
                          Having read chapter 9 and chapter 12, I had earlier moved my application from explicit hibernate session/transaction to work with Spring AOP.
                          Wired up the txManager, sessionFactory, etc. and it works.

                          Code:
                          <?xml version="1.0" encoding="UTF-8"?>
                          <beans xsi:schemaLocation="
                          http://www.springframework.org/schema/beans
                          http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
                          http://www.springframework.org/schema/security
                          http://www.springframework.org/schema/security/spring-security-2.0.xsd
                          http://www.springframework.org/schema/aop
                          http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
                          http://www.springframework.org/schema/tx
                          http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
                          "
                          xmlns="http://www.springframework.org/schema/beans"
                          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                          xmlns:sec="http://www.springframework.org/schema/security"
                          xmlns:aop="http://www.springframework.org/schema/aop"
                          xmlns:tx="http://www.springframework.org/schema/tx"
                          >
                          
                              <!-- Based on Chapter 9; works when DAO (data.Data) extends HibernateDaoSupport. -->
                          
                              <!-- Hibernate local transactions: -->
                              <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
                                  <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration"/>
                                  <property name="configLocations">
                                      <list>
                                      <value>classpath:customerdb.cfg.xml</value>
                                      <value>classpath:generic.cfg.xml</value>
                                      </list>
                                  </property>
                              </bean>
                          
                              <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                                  <property name="sessionFactory" ref="sessionFactory" />
                              </bean>
                          
                            <!-- the transactional advice (i.e. what 'happens'; see the <aop:advisor/> bean below) -->
                            <tx:advice id="txAdvice" transaction-manager="txManager">
                              <!-- the transactional semantics... -->
                              <tx:attributes>
                                <!-- all methods starting with 'get' are read-only -->
                                <tx:method name="get*" read-only="true"/>
                                <tx:method name="find*" read-only="true"/>
                                <!-- other methods use the default transaction settings (see below) -->
                                <tx:method name="*"/>
                              </tx:attributes>
                            </tx:advice>
                            
                            <!-- ensure that the above transactional advice runs for any execution
                                of an operation defined by the FooService interface -->
                            <aop:config>
                              <aop:pointcut id="dataOperation" expression="execution(public * com.local.data.Data.*(..))"/>
                              <aop:advisor advice-ref="txAdvice" pointcut-ref="dataOperation"/>
                            </aop:config>
                          
                            <!-- this is the service object that we want to make transactional -->
                            <bean id="sessionData" class="com.local.data.Data" scope="prototype">
                              <constructor-arg type="com.local.user.IUser"><null/></constructor-arg>
                              <property name="sessionFactory" ref="sessionFactory"/>
                              <property name="txManager" ref="txManager"/>
                            </bean>
                          
                          </beans>

                          But that was using the HibernateDaoSupport base class.
                          So i took out that base class, and added my own: setSessionFactory(); and getSession();
                          Modeled on the examples in 12.2.5 [not so complex as the code in HibernateDaoSupport]

                          Code:
                              // Spring setter: (for Hibernate 3.1 DAO pattern)
                              public void setSessionFactory(SessionFactory sf) { this.sessionFactory = sf; }
                              private SessionFactory sessionFactory;
                          
                              // do not rely on Spring's HibernateDaoSupport (base class)
                              public Session getSession() { return sessionFactory.getCurrentSession(); }

                          But now i'm not finding the transaction, although it appears the Proxy22 is doing something with the TransactionIntercepter:
                          Code:
                          2009-04-16 17:19:13,200 [main] DEBUG com.local.data.Data - Data.newData(): caught:
                          org.hibernate.HibernateException: createQuery is not valid without active transaction
                          	at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:297) [hibernate3.jar:3.2.4.sp1]
                          	at $Proxy23.createQuery(Unknown Source) [na:na]
                          	at com.local.data.Data.getFirstAccount(Data.java:162) [classes/:na]
                          	at com.local.data.Data.initAccount(Data.java:152) [classes/:na]
                          	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [na:1.5.0_12]
                          	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [na:1.5.0_12]
                          	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [na:1.5.0_12]
                          	at java.lang.reflect.Method.invoke(Method.java:585) [na:1.5.0_12]
                          	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310) [spring-2.5.4.jar:2.5.4]
                          	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182) [spring-2.5.4.jar:2.5.4]
                          	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149) [spring-2.5.4.jar:2.5.4]
                          	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106) [spring-2.5.4.jar:2.5.4]
                          	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) [spring-2.5.4.jar:2.5.4]
                          	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89) [spring-2.5.4.jar:2.5.4]
                          	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) [spring-2.5.4.jar:2.5.4]
                          	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) [spring-2.5.4.jar:2.5.4]
                          	at $Proxy22.initAccount(Unknown Source) [na:na]
                          	at com.local.data.Data.newData(Data.java:134) [classes/:na]
                          My "DAO" (com.local.data.Data) is configured as a "prototype", and has a static "factory" method newData()
                          which gets an instance from the ApplicationContext, and calls initAccount()/getFirstAccount() which does the hibernate query.
                          Code:
                              public AccountDTO getFirstAccount()
                          	...
                              Query query = getSession().createQuery(hql);
                          And this works when using HibernateDaoSupport as the base class,
                          Can anyone suggest what else I need to make this work without HibernateDaoSupport?

                          Comment


                          • #14
                            getSession() for Spring-managed Transactions

                            this post: http://forum.springsource.org/showth...rt+transaction
                            confirms that you need the more complex getSession() to the the correct Session:
                            Code:
                                public Session getSession() {
                                    return SessionFactoryUtils.getSession(sessionFactory, false);
                                }
                            So now my app works again.

                            But: Is the documentation/example in 12.2.5 incorrect?
                            How/Does this work?
                            Code:
                            12.2.5. Implementing DAOs based on plain Hibernate 3 API
                            Hibernate 3 provides a feature called "contextual Sessions", 
                            where Hibernate itself manages one current Session per transaction. 
                            This is roughly equivalent to Spring's synchronization of one Hibernate Session per transaction. 
                            A corresponding DAO implementation looks like as follows, based on the plain Hibernate API:
                            
                            public class ProductDaoImpl implements ProductDao {
                            
                                private SessionFactory sessionFactory;
                            
                                public void setSessionFactory(SessionFactory sessionFactory) {
                                    this.sessionFactory = sessionFactory;
                                }
                            
                                public Collection loadProductsByCategory(String category) {
                                    return this.sessionFactory.getCurrentSession()
                                            .createQuery("from test.Product product where product.category=?")
                                            .setParameter(0, category)
                                            .list();
                                }
                            }

                            Comment


                            • #15
                              With proper configuration you don't and you shouldn't need it. I only use the getCurrentSession. It would defy the purpose of not extending HibernateDaoSupport because you now still rely on spring and don't have a clean dao.

                              Just a few question because for some reasion your configuration and way of usage seems way to complex. Why does it have to be a prototype and why do you need the newData factory?! From my point of view that makes your code way to complex, not simply inject it and make it a singleton.

                              Also does your Data implement and interface? If it doesn't your proxy doesn't do much then you will need class proxying.

                              Comment

                              Working...
                              X