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

发布于 2021-11-29 00:13:25 字数 232 浏览 777 评论 4

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

这可能吗? 我该怎么做?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

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

评论(4

桃扇骨 2022-06-07 22:46:44

我不知道您当前的 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>

然后,您可以简单地将您的 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>

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 22:46:44

我不知道使用 Spring 可以轻松解决您的问题。

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

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

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 22:46:41

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

有关详细信息,请参阅这个问题

这篇博文 关于 Spring 中的动态数据源路由。

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 22:46:40

您可以定义一个抽象 bean 并使用 bean 继承。 这意味着您将拥有一个用作模板的 bean 定义,并且您可能有多个 bean 只是复制父 bean 设置的属性。

下面是一个示例:

<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>

使用“抽象”属性可以确保 bean 不会被实例化,它将仅用作模板。

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击“接受”或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文