我正在尝试在OSGi(Equinox)环境中使用Hibernate / Spring。如果我明确地将它指向Persistence.xml中的Entity类,那么它的效果很好:
<class>com.es.t.eee.domain.StuffSource</class>
<class>com.es.t.eee.domain.PostalAddress</class>
我想要的是让Hibernate“找到”所有实体类,就像它在OSGi环境之外一样。
Hibernate正在寻找@Entities的正确包:
Searching mapped entities in jar/par: bundleresource://34/
WARN 27-07 15:30:24,235 (InputStreamZippedJarVisitor.java:doProcessElements:41):
Unable to find file (ignored): bundleresource://34/
它看起来应该可以工作,但是当它到了查看Bundle Jar for @Entities的时候,会发生异常,我不知道为什么。我已经包含了Hibernate正在吐出的日志的重要部分。
有没有人有任何想法我做错了什么或这里的问题是什么?
我正在使用:
这是Hibernate解析Persistence.xml的地方
INFO 27-07 15:30:24,110 (Version.java:<clinit>:15):
Hibernate Annotations 3.4.0.GA
INFO 27-07 15:30:24,110 (Environment.java:<clinit>:543):
Hibernate 3.3.0.SP1
INFO 27-07 15:30:24,110 (Environment.java:<clinit>:576):
hibernate.properties not found
INFO 27-07 15:30:24,126 (Environment.java:buildBytecodeProvider:709):
Bytecode provider name : javassist
INFO 27-07 15:30:24,126 (Environment.java:<clinit>:627):
using JDK 1.4 java.sql.Timestamp handling
INFO 27-07 15:30:24,157 (Version.java:<clinit>:14):
Hibernate Commons Annotations 3.1.0.GA
INFO 27-07 15:30:24,157 (Version.java:<clinit>:16):
Hibernate EntityManager 3.4.0.GA
DEBUG 27-07 15:30:24,219 (Ejb3Configuration.java:configure:312):
Processing PersistenceUnitInfo [
name: unit.postgresql
persistence provider classname: null
classloader: BundleDelegatingClassLoader for [DatabaseObjects (DatabaseObjects)]
Temporary classloader: org.springframework.instrument.classloading.SimpleThrowawayClassLoader@11b50a1
excludeUnlistedClasses: true
JTA datasource: null
Non JTA datasource: com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 1000, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1012f6d821goxcok12zcw86|174f02c, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> org.postgresql.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1012f6d821goxcok12zcw86|174f02c, idleConnectionTestPeriod -> 0, initialPoolSize -> 5, jdbcUrl -> jdbc:postgresql://localhost:5432/test2, lastAcquisitionFailureDefaultUser -> null, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 100, maxStatements -> 100, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> false ]
Transaction type: RESOURCE_LOCAL
PU root URL: bundleresource://34/
Jar files URLs []
Managed classes names []
Mapping files names []
Properties [
hibernate.default_batch_fetch_size: 500
hibernate.cache.provider_class: net.sf.ehcache.hibernate.EhCacheProvider
hibernate.dialect: org.hibernate.dialect.PostgreSQLDialect
hibernate.max_fetch_depth: 5
hibernate.query.factory_class: org.hibernate.hql.ast.ASTQueryTranslatorFactory
hibernate.format_sql: false
hibernate.jdbc.batch_size: 1000
hibernate.use_outer_join: true
hibernate.archive.autodetection: class
hibernate.show_sql: false
hibernate.bytecode.provider: cglib]
这是错误发生的地方,因为它试图找到实体:
DEBUG 27-07 15:30:24,235 (Ejb3Configuration.java:getDetectedArtifacts:562):
Detect class: true; detect hbm: false
DEBUG 27-07 15:30:24,235 (Ejb3Configuration.java:getDetectedArtifacts:562):
Detect class: true; detect hbm: false
DEBUG 27-07 15:30:24,235 (AbstractJarVisitor.java:unqualify:116):
Searching mapped entities in jar/par: bundleresource://34/
WARN 27-07 15:30:24,235 (InputStreamZippedJarVisitor.java:doProcessElements:41):
Unable to find file (ignored): bundleresource://34/
java.lang.NullPointerException: in is null
at java.util.zip.ZipInputStream.<init>(Unknown Source)
at java.util.jar.JarInputStream.<init>(Unknown Source)
at java.util.jar.JarInputStream.<init>(Unknown Source)
at org.hibernate.ejb.packaging.InputStreamZippedJarVisitor.doProcessElements(InputStreamZippedJarVisitor.java:37)
at org.hibernate.ejb.packaging.AbstractJarVisitor.getMatchingEntries(AbstractJarVisitor.java:139)
at org.hibernate.ejb.Ejb3Configuration.addScannedEntries(Ejb3Configuration.java:287)
at org.hibernate.ejb.Ejb3Configuration.scanForClasses(Ejb3Configuration.java:614)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:360)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:131)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:224)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:291)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1369)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1335)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.beans.factory.support.AbstractBeanFactory.isSingleton(AbstractBeanFactory.java:366)
at org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean.afterPropertiesSet(OsgiServiceFactoryBean.java:235)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1369)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1335)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:423)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:288)
at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:145)
at java.lang.Thread.run(Unknown Source)
答案 0 :(得分:5)
此博客shows how it can be handled与Spring的动态模块。 基于该博客,您将在应用程序上下文中为DAO和Service bean创建bean定义。 DAO引用了hibernate sessionFactory bean:
<bean id="stuffDao" class="com.es.t.eee.domain.dao.StuffSourceDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="stuffService"
class="com.es.t.eee.domain.dao.StuffServiceImpl">
<property name="stuffDao" ref="stuffDao"/>
</bean>
<bean id="stuffSource"
class="com.es.t.eee.domain.StuffSource" scope="prototype"/>
StuffSourceDaoImpl将实现store()方法来持久化StuffSource,它将StuffSource传递给HibernateTemplate以实际执行持久性。
为了避免必须定义persistence.xml文件或指定每个实体,您可以使用AnnotationSessionFactoryBean和通配符来包含包含您的实体的包中的所有类型(您可能希望设置packagesToScan属性,我没试过这个,它可能会让你回到原来的问题):
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="hibernateProperties">
<props>
<!--etc-->
</props>
</property>
<!-- set either one of these properties -->
<property name="annotatedClasses">
<list>
<value>com.es.t.eee.domain.StuffSource</value>
<value>com.es.t.eee.domain.PostalAddress</value>
</list>
</property>
<property name="packagesToScan">
<list>
<value>com.es.t.eee.domain</value>
</list>
</property>
</bean>
要使用它,你将获得BundleContext,从上下文中获取服务和bean,然后继续正常运行:
String serviceName = StuffService .class.getName();
StuffService service =
(StuffService )context.getService(context.getServiceReference(serviceName));
String stuffName = StuffSource.class.getName();
StuffSource stuffSource =
(StuffSource) context.getService(context.getServiceReference(stuffName ));
//do whatever with StuffSource
...
service.store(stuffSource );
您可能还想查看讨论所涉及的一些问题的OSGi Alliance blog。来自OSGi Alliance博客:
Hibernate操纵类路径,这样的程序通常与基于OSGi的系统不能很好地协同工作。原因是在许多系统中,模块之间的类可见性或多或少是不受限制的。在OSGi框架中,类路径被很好地定义和限制。这为我们提供了很多好的功能,但是当我们想要使用一个在成长时渴望成为类加载器的库时,它也给我们带来了痛苦。 ...
要使用Hibernate,您需要一个Session对象。您可以从SessionFactory获取Session对象。要获取SessionFactory,您需要使用Configuration对象创建它。 Configuration对象是从配置XML文件创建的。默认情况下,Hibernate会从JAR文件的根目录加载它,但是,如果需要,您可以手动将类添加到配置中。
答案 1 :(得分:1)
之前的回复提到关于Hibernate和OSGi问题的OSGi博客文章是一个内容丰富的阅读。
我建议退一步思考传统Java应用程序中的假设,以及它们在OSGi中的有效性如何:
如果在提供实体类的任何包之前启动Hibernate包,您的应用程序将如何工作?即使扫描实体类有效,它也找不到。
在传统Java中,由于平面类路径,所有类在启动时都可用,但在OSGi类中,只有在启动贡献包并导入包时才可用。
OSGi需要明确连接依赖关系;如果你不导入一个包/包,那么你就看不到那些包/包中的类。
由于您说明确配置实体类是有效的,我假设您使用以下其中一项来进行依赖关系连接:
Rich Seller的建议应该有效(我还没有测试过),但你仍然被迫导入包含实体类的软件包,虽然我认为没有任何问题,所提议的解决方案提供了包扫描的选项,而不是明确指定每个实体类。
现在选项1很简单,选项2涉及大量工作。这完全取决于您需要从Hibernate自动添加/删除实体类而无需显式指定包/类。