java 如何在 Spring 中定义多个 sessionfactory 实例?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/794496/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 13:49:37  来源:igfitidea点击:

How can I define multiple sessionfactory instances in Spring?

javahibernatespring

提问by Chris R

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.

我想在一个 spring 应用程序中有多个 Hibernate SessionFactories,除了 DataSource 之外,所有这些都具有相同的配置。理想情况下,我会按名称获取特定的 SessionFactory。我需要能够根据运行时状态执行此操作,并且无法确定在应用程序启动时需要哪些会话工厂。基本上,我需要一个 SessionFactoryTemplate 或类似的东西。

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

这可能吗?我该怎么做?

回答by victor hugo

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.

您可以定义一个抽象 bean 并使用 bean 继承。这意味着您将有一个用作模板的 bean 定义,并且您可能有多个 bean,只是复制父 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.

使用属性 'abstract' 可以确保 bean 不会被实例化,它只会用作模板。

More info here: link text

更多信息在这里:链接文本

回答by alasdairg

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?

您确定需要多个 SessionFactories 吗?如果所有映射/配置都相同并且您只有多个相同的数据库(例如在多租户应用程序中?),那么拥有一个连接到动态提供适当数据库连接的数据源的单个 SessionFactory 怎么样?

See this questionfor more details:

有关更多详细信息,请参阅此问题

And this blog poston Dynamic DataSource Routing in Spring.

还有这篇关于 Spring 中的动态数据源路由的博客文章

回答by matt b

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

我不知道您当前的 bean 定义现在是什么样子,但您不会……定义第二个 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:

然后,您可以简单地将您的 DAO 与一个 sessionFactory 与另一个连接起来:

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

<bean id="myCompanyDao" class="product.ProductDaoImpl">
  <property name="sessionFactory" ref="mySessionFactory2"/>
</bean>

回答by javashlook

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

我不知道使用 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 postexplains 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.

但是,您可以使用 Hibernate Interceptors,前提是您的特定数据库/数据源可以通过一个主/管理数据库连接访问。这篇博文详细解释了如何做,但其要点是动态替换 Hibernate 生成的 SQL 语句中的表名,用限定名标识不同的数据库。这相对容易理解和维护,并且在我公司的多租户设置中运行良好。

Apart from that, you can try writing your own TransactionManager, using the HibernateTransactionManageras 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.

除此之外,您可以尝试编写自己的TransactionManager,以HibernateTransactionManager为起点,添加对使用多个会话工厂的支持。但是,这意味着您必须真正深入了解 Spring ORM 支持的内部结构,这是我尝试过的方法,但后来放弃支持第一种方法。我相信它可以通过适度的努力来完成,但之前的解决方案已经为我们完成了这项工作。