Announcement Announcement Module
Collapse
No announcement yet.
SessionFactory and LocalSessionFactoryBean in Hibernate caching and Tests Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • SessionFactory and LocalSessionFactoryBean in Hibernate caching and Tests

    We've got a bunch of tests which subclass AbstractTransactionalDataSourceSpringContextTests.

    Many of those tests need access to the SessionFactory to do things like flushing and cache evicting.

    This is working great by using....

    Code:
    	<bean id="hibernateSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    		<property name="dataSource" ref="dataSource"/>
    And...

    Code:
    	//injected by Spring (auto-wired by name)
    	SessionFactory hibernateSessionFactory;
    	public void setHibernateSessionFactory(SessionFactory hibernateSessionFactory) {this.hibernateSessionFactory = hibernateSessionFactory;}
    	
    	public void test_getQuestions_nullSiteIds_nullSiteDao() {
    		hibernateSessionFactory.evict(...);
    But now we find we're in need of the LocalSessionFactoryBean class in this same test class because only it has the getConf() method available.

    We can easily get one or the other. If we want a SessionFactory we do this...

    Code:
    SessionFactory hibernateSessionFactory;
    public void setHibernateSessionFactory(SessionFactory hibernateSessionFactory) {this.hibernateSessionFactory = hibernateSessionFactory;}

    And if we want a LocalSessionFactoryBean we do this...

    Code:
    LocalSessionFactoryBean hibernateSessionFactory;
    public void setHibernateSessionFactory(SessionFactory hibernateSessionFactory) {this.hibernateSessionFactory = hibernateSessionFactory;}
    But what if we want them *both* (in the same test class).

    Our current solution has us creating an alias for the hibernateSessionFactoryBean in our config file like this:

    Code:
    <alias name="hibernateSessionFactory" alias="localSessionFactoryBean" />
    And then just creating two different setters that Spring can auto-wire to:

    Code:
    SessionFactory hibernateSessionFactory;
    public void setHibernateSessionFactory(SessionFactory hibernateSessionFactory) {this.hibernateSessionFactory = hibernateSessionFactory;}
    
    LocalSessionFactoryBean localSessionFactoryBean;
    public void setLocalSessionFactoryBean(LocalSessionFactoryBean localSessionFactoryBean) {this.localSessionFactoryBean= localSessionFactoryBean;}
    Sort of seems like a hack, though. Is there a better technique?

    Thanks!

    - Gary

  • #2
    Aren't these methods on the Session? Then SessionFactory.getCurrentSession() should work.

    Joerg

    Comment


    • #3
      > Aren't these methods on the Session?

      No.

      > Then SessionFactory.getCurrentSession() should work.

      Unfortunately it does not. The Hibernate Session does not expose the configuration. And neither does the Hibernate SessionFactory, for that matter.

      This inability to get a reference back to the configuration object is one of my pet-peeves about Hibernate.

      And it's one of the nifty things about Spring. Since the HibernateSessionFactory is being created under Spring's control, Spring does the "right thing" (IMO) and does keep a reference to the Configuration that it will let you retrieve.

      So LocalSessionFactoryBean (The Spring class in charge of creating the Hibernate SessionFactory) implements and exposes the .getConfiguration() method we need.

      So the question remains. What if you need a reference to BOTH the LocalSessionFactoryBean object and the Hibernate SessionFactory object that it creates?

      The alias solution works but it seems like a hack.

      - Gary

      Comment


      • #4
        Originally posted by gaffonso View Post
        > Aren't these methods on the Session?
        The Session interface has at least both evict(Object) and flush().

        Originally posted by gaffonso View Post
        > Then SessionFactory.getCurrentSession() should work.
        I saw it is not static, so you need the instance anyway.

        When rereading your original post I noticed I missed the main point of it.

        Originally posted by gaffonso View Post
        Our current solution has us creating an alias for the hibernateSessionFactoryBean in our config file like this:

        Code:
        <alias name="hibernateSessionFactory" alias="localSessionFactoryBean" />
        And then just creating two different setters that Spring can auto-wire to:

        Code:
        SessionFactory hibernateSessionFactory;
        public void setHibernateSessionFactory(SessionFactory hibernateSessionFactory) {this.hibernateSessionFactory = hibernateSessionFactory;}
        
        LocalSessionFactoryBean localSessionFactoryBean;
        public void setLocalSessionFactoryBean(LocalSessionFactoryBean localSessionFactoryBean) {this.localSessionFactoryBean= localSessionFactoryBean;}
        Are you really sure this is working? I can't believe it. An alias of a bean can not be different than the actual bean. If it is so I consider this a bug in Spring.

        The usual way to get FactoryBeans like the LocalSessionFactoryBean injected instead of the objects they are creating is to prefix their name with & (written &amp; since it is XML and & must be escaped):

        Code:
        <bean>
          <property name="sessionFactory" ref="sessionFactory"/>
          <property name="sessionFactoryBean" ref="&amp;sessionFactory"/>
        </bean>
        Joerg

        Comment

        Working...
        X