如何配置hibernate以使用特定于上下文的连接信息?

时间:2021-12-20 13:26:56

I'm writing a Java SE (Note, not Java EE) application using Hibernate, and I need to provide a different connection to Hibernate for each thread of execution. These connections must be pooled, and each one has at the very least different authentication and, possibly, a different JDBC URL. The connections will be re-used (as can be inferred from the pooling requirement).

我正在使用Hibernate编写Java SE(注意,而不是Java EE)应用程序,我需要为每个执行线程提供与Hibernate的不同连接。必须合并这些连接,并且每个连接至少具有不同的身份验证,并且可能具有不同的JDBC URL。连接将被重用(可以从池化要求中推断出来)。

What parts of Hibernate/C3P0/et al do I have to override? Can this be accomplished with those tools, or do I need to write my own pooling data source?

我必须覆盖Hibernate / C3P0 / et的哪些部分?这可以用这些工具完成,还是我需要编写自己的池数据源?

2 个解决方案

#1


I think the best course of action would be creating a SessionFactory for each data source, with possibly pooled connections - that's what's eqbridges suggested in his answer.

我认为最好的做法是为每个数据源创建一个SessionFactory,可能有汇集连接 - 这就是他的答案中提出的eqbridges。

Now, Hibernate does have a ConnectionProvider hook, so I suppose you could write an implementation that would return Connections to different data sources, depending on current thread of execution and some additional parameters. Theoretically, you can then have one SessionFactory instance, which will be using different connections to different databases, supplied by your custom ConnectionProvider implementation. But, one SessionFactory holds quite a bit of data, and that data is then used by Hibernate internally, when opening a Session for a unit of work. Plus, there's a second-level cache associated with it as well.

现在,Hibernate确实有一个ConnectionProvider挂钩,所以我想你可以编写一个实现,它会将Connections返回到不同的数据源,具体取决于当前的执行线程和一些其他参数。从理论上讲,您可以拥有一个SessionFactory实例,该实例将使用由自定义ConnectionProvider实现提供的不同数据库的不同连接。但是,一个SessionFactory保存了相当多的数据,然后在为一个工作单元打开一个Session时,Hibernate会在内部使用该数据。另外,还有与之关联的二级缓存。

Unfortunately, how will the factory and Sessions you open from it behave in the face of such a provider is anybody's guess. It feels like a hack to me, and I doubt it was ever considered a viable use-case for a SessionFactory. It can possibly lead to all kinds of, possibly very subtle, bugs or data corruption.

不幸的是,如果有人猜测,你打开的工厂和Sessions如何面对这样的供应商。这对我来说感觉像是一个黑客,我怀疑它曾被认为是SessionFactory的可行用例。它可能导致各种各样的,可能非常微妙的错误或数据损坏。

On another note, be sure to exactly measure the cost of creating multiple SessionFactories - it may not be as high as you think. Be sure to compare that with the cost of simply opening the needed JDBC connections. I don't know what kind of results you might get, but I think you should be sure about performance before you resort to more hackish solutions.

另外,请务必准确衡量创建多个SessionFactories的成本 - 它可能没有您想象的那么高。请务必将其与仅打开所需JDBC连接的成本进行比较。我不知道你可能会得到什么样的结果,但我认为你应该在采用更多hackish解决方案之前确定性能。

#2


You have two questions here:

你有两个问题:

  1. Connections are not thread safe, so each thread must have its own connection. Since you're working with Hibernate, what your application sees is actually a Session obtained from a SessionFactory. To utilize this, you call the SessionFactory#getCurrentSession() method, and configure the current session context in hibernate.cfg.xml:
    <property name="current\_session\_context\_class">thread</property>
    If you've properly configured thread pooling (using c3po or whatever pooling mechanism you favor) in hibernate.cfg.xml, then each thread will get a connection from that pool.
  2. 连接不是线程安全的,因此每个线程必须有自己的连接。由于您正在使用Hibernate,您的应用程序看到的实际上是从SessionFactory获取的Session。要使用它,可以调用SessionFactory#getCurrentSession()方法,并在hibernate.cfg.xml中配置当前会话上下文: thread 如果你已经在hibernate.cfg.xml中正确配置的线程池(使用c3po或您喜欢的任何池化机制),然后每个线程将从该池获得连接。

  3. To maintain multiple data sources that the application may need to work with, then you need to configure a separate SessionFactory for each JDBC url you'd like to access. In your application you'll need to have some means of selecting with SessionFactory you'll need to choose (e.g. "client ID"), using this you can manage each of the SessionFactory instances in a Map or somesuch data structure (in a Java EE app you'd get a reference from JNDI).
  4. 要维护应用程序可能需要使用的多个数据源,您需要为要访问的每个JDBC URL配置单独的SessionFactory。在您的应用程序中,您需要使用SessionFactory选择一些方法来选择(例如“客户端ID”),使用它可以管理Map中的每个SessionFactory实例或某些数据结构(在Java中) EE应用程序,您将从JNDI获得参考)。

To summarize (and generalize), basically a SessionFactory is essentially huge wrapper around a DataSource (and attendant connection pool). It is read-only (and hence thread safe), heavyweight and static, constructed once, and knows everything it needs to about a given DataSource.

总结(并概括),基本上SessionFactory本质上是围绕DataSource(和话务员连接池)的巨大包装器。它是只读的(因此是线程安全的),重量级和静态,构造一次,并且知道它对给定DataSource所需的一切。

A Session, on the other hand is essentially a lightweight wrapper around a Connection. It is not thread safe, often short-lived, and intended to be used and then thrown away.

另一方面,Session实际上是一个围绕Connection的轻量级包装器。它不是线程安全的,通常是短暂的,并且打算使用然后丢弃。

Hope this helps!

希望这可以帮助!

#1


I think the best course of action would be creating a SessionFactory for each data source, with possibly pooled connections - that's what's eqbridges suggested in his answer.

我认为最好的做法是为每个数据源创建一个SessionFactory,可能有汇集连接 - 这就是他的答案中提出的eqbridges。

Now, Hibernate does have a ConnectionProvider hook, so I suppose you could write an implementation that would return Connections to different data sources, depending on current thread of execution and some additional parameters. Theoretically, you can then have one SessionFactory instance, which will be using different connections to different databases, supplied by your custom ConnectionProvider implementation. But, one SessionFactory holds quite a bit of data, and that data is then used by Hibernate internally, when opening a Session for a unit of work. Plus, there's a second-level cache associated with it as well.

现在,Hibernate确实有一个ConnectionProvider挂钩,所以我想你可以编写一个实现,它会将Connections返回到不同的数据源,具体取决于当前的执行线程和一些其他参数。从理论上讲,您可以拥有一个SessionFactory实例,该实例将使用由自定义ConnectionProvider实现提供的不同数据库的不同连接。但是,一个SessionFactory保存了相当多的数据,然后在为一个工作单元打开一个Session时,Hibernate会在内部使用该数据。另外,还有与之关联的二级缓存。

Unfortunately, how will the factory and Sessions you open from it behave in the face of such a provider is anybody's guess. It feels like a hack to me, and I doubt it was ever considered a viable use-case for a SessionFactory. It can possibly lead to all kinds of, possibly very subtle, bugs or data corruption.

不幸的是,如果有人猜测,你打开的工厂和Sessions如何面对这样的供应商。这对我来说感觉像是一个黑客,我怀疑它曾被认为是SessionFactory的可行用例。它可能导致各种各样的,可能非常微妙的错误或数据损坏。

On another note, be sure to exactly measure the cost of creating multiple SessionFactories - it may not be as high as you think. Be sure to compare that with the cost of simply opening the needed JDBC connections. I don't know what kind of results you might get, but I think you should be sure about performance before you resort to more hackish solutions.

另外,请务必准确衡量创建多个SessionFactories的成本 - 它可能没有您想象的那么高。请务必将其与仅打开所需JDBC连接的成本进行比较。我不知道你可能会得到什么样的结果,但我认为你应该在采用更多hackish解决方案之前确定性能。

#2


You have two questions here:

你有两个问题:

  1. Connections are not thread safe, so each thread must have its own connection. Since you're working with Hibernate, what your application sees is actually a Session obtained from a SessionFactory. To utilize this, you call the SessionFactory#getCurrentSession() method, and configure the current session context in hibernate.cfg.xml:
    <property name="current\_session\_context\_class">thread</property>
    If you've properly configured thread pooling (using c3po or whatever pooling mechanism you favor) in hibernate.cfg.xml, then each thread will get a connection from that pool.
  2. 连接不是线程安全的,因此每个线程必须有自己的连接。由于您正在使用Hibernate,您的应用程序看到的实际上是从SessionFactory获取的Session。要使用它,可以调用SessionFactory#getCurrentSession()方法,并在hibernate.cfg.xml中配置当前会话上下文: thread 如果你已经在hibernate.cfg.xml中正确配置的线程池(使用c3po或您喜欢的任何池化机制),然后每个线程将从该池获得连接。

  3. To maintain multiple data sources that the application may need to work with, then you need to configure a separate SessionFactory for each JDBC url you'd like to access. In your application you'll need to have some means of selecting with SessionFactory you'll need to choose (e.g. "client ID"), using this you can manage each of the SessionFactory instances in a Map or somesuch data structure (in a Java EE app you'd get a reference from JNDI).
  4. 要维护应用程序可能需要使用的多个数据源,您需要为要访问的每个JDBC URL配置单独的SessionFactory。在您的应用程序中,您需要使用SessionFactory选择一些方法来选择(例如“客户端ID”),使用它可以管理Map中的每个SessionFactory实例或某些数据结构(在Java中) EE应用程序,您将从JNDI获得参考)。

To summarize (and generalize), basically a SessionFactory is essentially huge wrapper around a DataSource (and attendant connection pool). It is read-only (and hence thread safe), heavyweight and static, constructed once, and knows everything it needs to about a given DataSource.

总结(并概括),基本上SessionFactory本质上是围绕DataSource(和话务员连接池)的巨大包装器。它是只读的(因此是线程安全的),重量级和静态,构造一次,并且知道它对给定DataSource所需的一切。

A Session, on the other hand is essentially a lightweight wrapper around a Connection. It is not thread safe, often short-lived, and intended to be used and then thrown away.

另一方面,Session实际上是一个围绕Connection的轻量级包装器。它不是线程安全的,通常是短暂的,并且打算使用然后丢弃。

Hope this helps!

希望这可以帮助!