Announcement Announcement Module
Collapse
No announcement yet.
Newbie Hibernate Thread-local Transactions Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Newbie Hibernate Thread-local Transactions

    Hello,

    This may sound silly, but how do I declare the creation of thread-local Hibernate sessions with simple JDBC transactions? I'm writing a relatively simple web application, and I need thread-local sessions to take advantage of Hibernate's lazy-loading proxies in my presentation layer. I need some sort of intercepter that will create a session before the dispatcher servlet passes control to my controller and close the session after the presentation layer returns.

    I've been looking through all the documentation, but I understand very little about JTA or database clusters -- and the Spring source code makes even less sense. Help!

    Matthew

  • #2
    Take a look at org.springframework.orm.hibernate.support.OpenSess ionInViewFilter.
    You can also search the forums for more help for how to configure this Filter.
    HTH

    Comment


    • #3
      Okay, thanks. I have a follow-up problem, if you don't mind.

      I set up a thread-local transaction using the interceptor and a HibernateTransactionManager. I have no idea if the transaction manager is actually working, as I didn't wire it to anything, but ... anyway ...

      Reading data from the database works just fine, but when I try to save new objects to the database in my DAO, nothing happens.

      Code:
      public class TeamDao extends HibernateDaoSupport implements TeamManager {
      
      	public void addSchool(School newSchool) {
      		getHibernateTemplate().save(newSchool);
      	}
      
      	// ...
      
      }
      In this case, the ID field in newSchool remains null (which is messing up my view, because it uses the resulting ID in a hyperlink), and nothing is written to the database. Any suggestions? I'm using PostgreSQL 7.4.6.

      My Spring XML configuration:

      Code:
        <bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
          <property name="sessionFactory"><ref bean="sessionFactory"/></property>
        </bean>  
      
        <bean name="teamManager" class="TeamDao">
          <property name="sessionFactory"><ref bean="sessionFactory"/></property>
        </bean>
      
        <bean name="openSessionInViewInterceptor" class="org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor">
             <property name="sessionFactory"><ref bean="sessionFactory"/></property>
        </bean>
      
        <bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
          <property name="interceptors">
            <list>
              <ref bean="openSessionInViewInterceptor"/>
            </list>
          </property>
        </bean>
      I have the same problem without transactionManager.

      Thanks again!

      Matthew

      Comment


      • #4
        modify your teamManager bean as follows:
        Code:
          <bean id="teamManager"  
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
            <property name="transactionManager">
              <ref bean="transactionManager"/>
            </property>
            <property name="target">
              <bean class="TeamDao"> 
                <property name="sessionFactory"><ref bean="sessionFactory"/></property> 
              </bean> 
            </property>
            <property name="transactionAttributes">
              <props>
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="*">PROPAGATION_REQUIRED</prop>
              </props>
            </property>
          </bean>
        HTH

        Comment


        • #5
          Thanks for all your help!

          The TransactionProxyFactoryBean initializes correctly when I start up my application, but I still have the same problem. The ID field is left null, and nothing is inserted into the database.

          Matthew

          Comment


          • #6
            could you show the mapping for class School? also, can you turn on show_sql in Hibernate configuration and verify if an Insert Sql Query is executed? is there any Exception in the log?

            Comment


            • #7
              Howdy.

              The log is filled with all sorts of select statements, but no insert statements or Hibernate exceptions. Also, the PostgreSQL sequence I use for generating keys is not advancing with each insert attempt. My mapping follows:

              Code:
              <?xml version="1.0" encoding="UTF-8"?>
              <!DOCTYPE hibernate-mapping PUBLIC
                        "-//Hibernate/Hibernate Mapping  DTD 2.0//EN"
                        "http&#58;//hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
              
              <hibernate-mapping>
              
                <class name="School" table="tbl_schools">
                  
                  <id name="id" type="int" column="school_id">
                    <generator class="sequence">
                      <param name="sequence">seq_school_id</param>
                    </generator>
                  </id>
              
                  <property name="created" type="date" insert="false"/>
                  
                  <property name="name" type="string"/>
                  
                  <property name="division" type="DivisionType"/>
              
                  <component name="address" class="Address" insert="true" update="true">
                    <property name="address1" type="string"/>
                    <property name="address2" type="string"/>
                    <property name="city"     type="string"/>
                    <property name="state"    type="StateType"/>
                    <property name="zip"      type="string"/>
                  </component>
                  
                  <set name="teams" inverse="true">
                    <key column="school_id"/>
                    <one-to-many class="Team"/>
                  </set>
                  
                  <set name="contacts" inverse="true">
                    <key column="school_id"/>
                    <one-to-many class="Contact"/>
                  </set>
                  
                </class>
                
                <query name="School.all.sorted"><!&#91;CDATA&#91;
                  from School as school
                  order by school.name asc
                &#93;&#93;></query>
              
              </hibernate-mapping>
              And the schema:

              Code:
              create sequence seq_school_id     minvalue 100    maxvalue 999;
              
              create table tbl_schools &#40;
                  school_id int default nextval&#40;'seq_school_id'&#41; primary key,
                  created   timestamp default now&#40;&#41; not null,
                  name      text not null,
                  division  char&#40;2&#41; not null, -- 'cc' or 'hs'
                  address1  text not null,
                  address2  text,
                  city      text not null,
                  state     char&#40;2&#41; not null, -- e.g., 'CA'
                  zip       char&#40;10&#41; not null
              &#41;;
              The application behaves like the transaction is never committed. Everything works when I use the SessionFactory directly -- without HibernateTemplate -- and manually commit my transaction or flush my session in the DAO.

              Thanks again!

              Matthew

              P.S. Happy Thanksgiving!

              Comment


              • #8
                I've been re-reading the documentation and looking through more Spring source code, and the whole transaction framework is beginning to make a lot of sense. However, I still can't get my application to write changes to the database. It looks like the transaction proxy should be committing after my DAO returns, but obviously something is amiss. (Oh how I wish I could set breakpoints in web applications...)

                I modified my OpenSessionInViewInterceptor configuration so it would flush after my controller returns ...

                Code:
                  <bean name="openSessionInViewInterceptor" class="org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor">
                    <property name="sessionFactory"><ref bean="sessionFactory"/></property>
                    <property name="flushMode">
                      <bean id="org.springframework.orm.hibernate.HibernateAccessor.FLUSH_AUTO"
                            class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>
                    </property>
                  </bean>
                ... but still no success.

                I turned on the debug-level output in the logs. I can see the interceptor flushing my session with "0 insertions, 0 updates, 0 deletions to 0 objects," but I see no mention of any Hibernate transactions as I would expect from, e.g., org/springframework/orm/hibernate/HibernateTransactionManager.java:371, which should output, "Opened new session [...] for Hibernate transaction."

                Matthew

                Comment


                • #9
                  That's strange indeed. I added some log output to my own code, and discovered that the doSubmit method in my controller is never invoked! For some reason, it isn't overriding the method from SimpleFormController ... nevermind that I copied the signature directly from SimpleFormController.java ...

                  Matthew

                  Comment


                  • #10
                    Geez ... My IDE somehow imported java.net.BindException rather than org.springframework.validation.BindException. :oops:

                    Thanks for your help! It's working now.

                    Matthew

                    Comment

                    Working...
                    X