5

我遇到了一个有点令人沮丧的问题。我使用 Apache Felix 作为我的 OSGi 框架,并且我还使用 Hibernate 来解决持久性问题。

我正在使用 Hibernate 的“osgi-bundle”版本(com.springsource.org.hibernate-3.2.6.ga.jar)。据我所知,这是 Hibernate Core,在 META-INF/MANIFEST.mf 中安装了一些额外的 osgi-metdata。此信息(Package-Export 和 Package-Import)对于 osgi 系统至关重要。

我的问题是 Hibernate 包找不到我的 JDBC 驱动程序。在springsource Hibernate bundle中加入Import语句感觉很不对劲。必须有一些更好的方法来解决这个问题。

4

5 回答 5

7

Hibernate 不是一个非常好的 OSGi 公民,因为 Hibernate 对类可见性所做的许多假设在 OSGi 容器中不再成立。

使用 JDBC 驱动程序加载的常用方法Class.forName(<jdbc class name>)在 OSGi 中不起作用,因为在这种情况下,Hibernate 将尝试加载驱动程序但找不到它,因为 Hibernate 不(也不应该)导入 JDBC 驱动程序包.

JDBC 驱动程序管理器还试图通过计算调用类的类加载器是否应该看到驱动程序来变得聪明,这也与 OSGi 冲突。

如果您使用 Spring 来配置 Hibernate,那么我建议您使用SimpleDriverDataSource该类,因为它在 OSGi 中有效,并且 Spring 允许您使用具体的数据源配置 Hibernate,而不是传递 Hibernate 需要实例化的类名。

一旦你解决了这个问题,你可能会遇到 Hibernate 看不到你的域类的问题。我只有 XML 映射方法的经验,我认为在 OSGi 中更简单,因为我认为注释方式需要某种 AOP 编织,这是 OSGi 当前的另一个痛点。

目前,除非您使用 Spring 的 dm Server 之类的东西,否则您需要更加熟悉 Java 的类加载机制以及如何使用 OSGi 的服务方法来解决 vanilla Java 和 OSGi 世界之间的不兼容问题。

具体来说,研究企业库如何使用上下文类加载器以及如何管理它。我正在使用 Spring dm 将遗留代码包装在 OSGi 服务中,因为这样可以轻松控制上下文类加载器。

于 2009-04-13T18:45:33.553 回答
3

您是否处理了正确的捆绑包开始订购?有一种方法可以设置每个包的启动级别,以便您的系统可以正确引导。如果某些激活器尝试直接获取服务,则可能需要正确的捆绑包启动级别。如果服务不可用,服务消费者就会被卡住。

尝试为您的捆绑包设置正确的启动级别并查看它是否有效。具体来说,您必须先使用 JDBC 驱动程序启动该包,然后再使用休眠包。

另一个问题可能是您有一些未解决的依赖项。确保一切都在那里。您可以通过获取 OSGi 控制台并询问服务列表来完成此操作。在 Equinox 中,这归结为 -console 命令行参数和 OSGi shell 中的“ss”后跟“diag”命令。

编辑(回答您的评论):

驱动程序由它们的接口注册。然后 Hibernate 可能通过其接口查找驱动程序,无需导入特定的驱动程序类。无论如何,这会引入对实现特定类的不希望的依赖。

于 2009-03-25T17:06:57.737 回答
3

在 OSGi 包中,您只能查看已导入包中的类和资源。Hibernate 包不会(也不应该)导入您的域类。因此,当 Hibernate 尝试处理 XML 映射文件时,它会抱怨找不到正在映射的类(您的域类)。

我们通过使用 Equinox 的伙伴策略解决了这个问题,因此每个提供域对象的包都是 Hibernate 的类加载伙伴。我不太喜欢这种方法,但我没有时间编写我脑海中的(希望如此)优雅的解决方案。

正如我在之前的文章中所说,对于 Hibernate 而言,操作上下文类加载器可能是最好的长期选择。

于 2009-07-01T12:26:21.843 回答
1

我前段时间遇到过类似的问题。解决方案是将 jdbc-provider bundle 和 jdbc-user bundle 注册为“buddies”。这是因为一个捆绑包不能使用来自另一个捆绑包的类(所以 jdbc 驱动程序也是如此),除非明确声明它。这是为 Eclipse 准备的,所以我认为它可能会对您有所帮助。

于 2009-05-07T17:53:42.510 回答
1

我还没有尝试过(因为我是反 RDBMS,因此也是反 ORM),但一种解决方案可能是使用 OSGi 片段。

创建一个包含您的域类的片段并将 Hibernate 包指定为主机。这个片段应该导出你的域类的包。

同样,您可以对要使用的 JDBC 驱动程序执行相同的操作。获取驱动程序类并将它们转换为以 Hibernate 作为主机包的 OSGi 片段。但是,您不必导出驱动程序包,因为它们只会被 Hibernate 包使用。

我怀疑Felix 9个月前没有完全支持片段,但现在看来它们肯定是:http: //osgithoughts.blogspot.com/2009/09/felix-now-fully-supports-osgi-fragments.html

于 2010-01-02T15:49:22.060 回答