How can I define multiple sessionfactory instances in Spring?

How can I define multiple sessionfactory instances in Spring?

夜无邪 发布于 2021-11-29 字数 495 浏览 775 回复 4 原文

I would like to have multiple Hibernate SessionFactories in a spring application, all of them with identical configurations except for the DataSource. Ideally, I would acquire a particular SessionFactory by name. I need to be able to do this based on runtime state, and it isn't possible to determine which session factories I will need at application startup time. Basically, I need a SessionFactoryTemplate or something like it.

Is this possible? How do I go about doing it?

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

眼藏柔 2022-06-07 4 楼

I don't know of an easy solution for your problem using Spring.

However, you could be able to use Hibernate Interceptors, provided that your particular databases/data-sources can be reached through one master/admin database connection. This blog post explains how in detail, but the gist of it is to dynamically replace table names in SQL statements that Hibernate generates, with qualified names identifying different databases. This is relatively easy to understand and maintain, and works well in my company's multi-tenant set-up.

Apart from that, you can try writing your own TransactionManager, using the HibernateTransactionManager as a starting point, adding support for working with multiple session factories. However, this would mean you having to really dive into Spring ORM support internals, and that is something I tried, but then scrapped in favor of the first approach. I'm sure it can be done with moderate effort, but the previous solution was already doing the job for us.

桃扇骨 2022-06-07 3 楼

I have no idea what your current bean definition looks like now, but wouldn't you just ... define a second SessionFactory?

<bean id="mySessionFactory1" 
   class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource1"/>
    <property name="mappingResources">
      <list>
        <value>product.hbm.xml</value>
      </list>
    </property>
    <property name="hibernateProperties">
      <value>
        hibernate.dialect=org.hibernate.dialect.HSQLDialect
      </value>
    </property>
</bean>

<bean id="mySessionFactory2"
   class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource2"/>
    ...
</bean>

You could then simply just wire your DAOs up with one sessionFactory vs the other:

<bean id="myProductDao" class="product.ProductDaoImpl">
  <property name="sessionFactory" ref="mySessionFactory1"/>
</bean>

<bean id="myCompanyDao" class="product.ProductDaoImpl">
  <property name="sessionFactory" ref="mySessionFactory2"/>
</bean>
余罪 2022-06-07 2 楼

Are you sure you need multiple SessionFactories? If all the mappings/configurations are the same and you just have multiple identical databases (e.g. in a multi-tenant app?), then how about having a single SessionFactory that connects to a DataSource which dynamically supplies the appropriate database connection?

See this question for more details:

And this blog post on Dynamic DataSource Routing in Spring.

节枝 2022-06-07 1 楼

You might define an abstract bean and use bean inheritance. This means you'll have a bean definition that works as a template and you may have multiple beans just copying the attributes set by the parent bean.

Here's an example:

<bean id="abstractSessionFactory" abstract="true"
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="mappingResources">
      <list>
        <value>product.hbm.xml</value>
      </list>
    </property>
    <property name="hibernateProperties">
      <value>
        hibernate.dialect=org.hibernate.dialect.HSQLDialect
      </value>
    </property>
</bean>

<bean id="mySessionFactory" parent="abstractSessionFactory">
    <property name="dataSource" ref="myDataSource"/>
    ...
</bean>

<bean id="mySessionFactory2" parent="abstractSessionFactory">
    <property name="dataSource" ref="myDataSource2"/>
    ...
</bean>

Using the attribute 'abstract' you ensure that bean won't be instantiated and it will be used just as a template.

More info here: link text