OSGi 中的 Hibernate 和 H2,缺少 Persistence Provider

Hibernate & H2 in OSGi, Persistence Provider missing

我正在开发一个需要数据库的 OSGi 应用程序。 我选择为我的数据库使用 H2 和 Hibernate。

如何相信 EntityManager 找不到名称为 "test" 的持久性文件。我不相信 PersistenceProvider 不是 运行。当 运行 没有 OSGI 但作为 MavenProject 我没有得到这个错误。

这是控制台输出:

Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=256m; support was removed in 8.0
osgi> ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...
Initial SessionFactory creation failed.javax.persistence.PersistenceException: No Persistence provider for EntityManager named test
!SESSION 2015-05-11 09:22:14.196 -----------------------------------------------
eclipse.buildId=unknown
java.version=1.8.0_25
java.vendor=Oracle Corporation
BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=de_DE
Command-line arguments:  -dev file:/Users/christianverdion/Documents/workspace/HibernateH2OSGi/.metadata/.plugins/org.eclipse.pde.core/HibernateH2OSGi/dev.properties -os macosx -ws cocoa -arch x86_64 -consoleLog -console

!ENTRY hibernateh2osgi 4 0 2015-05-11 09:22:16.029
!MESSAGE FrameworkEvent ERROR
!STACK 0
org.osgi.framework.BundleException: Exception in hibernateh2osgi.Activator.start() of bundle hibernateh2osgi.
 at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:792)
 at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:721)
 at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:936)
 at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:319)
 at org.eclipse.osgi.container.Module.doStart(Module.java:571)
 at org.eclipse.osgi.container.Module.start(Module.java:439)
 at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1582)
 at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1562)
 at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1533)
 at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1476)
 at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1)
 at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
 at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:340)
Caused by: java.lang.ExceptionInInitializerError
 at hibernateh2osgi.EntityManagerUtil.<clinit>(EntityManagerUtil.java:16)
 at hibernateh2osgi.DataProviderImpl.<init>(DataProviderImpl.java:15)
 at hibernateh2osgi.Activator.start(Activator.java:32)
 at org.eclipse.osgi.internal.framework.BundleContextImpl.run(BundleContextImpl.java:771)
 at org.eclipse.osgi.internal.framework.BundleContextImpl.run(BundleContextImpl.java:1)
 at java.security.AccessController.doPrivileged(Native Method)
 at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:764)
 ... 12 more
Caused by: javax.persistence.PersistenceException: No Persistence provider for EntityManager named test
 at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:61)
 at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
 at hibernateh2osgi.EntityManagerUtil.<clinit>(EntityManagerUtil.java:12)
 ... 18 more
Root exception:
java.lang.ExceptionInInitializerError
 at hibernateh2osgi.EntityManagerUtil.<clinit>(EntityManagerUtil.java:16)
 at hibernateh2osgi.DataProviderImpl.<init>(DataProviderImpl.java:15)
 at hibernateh2osgi.Activator.start(Activator.java:32)
 at org.eclipse.osgi.internal.framework.BundleContextImpl.run(BundleContextImpl.java:771)
 at org.eclipse.osgi.internal.framework.BundleContextImpl.run(BundleContextImpl.java:1)
 at java.security.AccessController.doPrivileged(Native Method)
 at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:764)
 at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:721)
 at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:936)
 at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:319)
 at org.eclipse.osgi.container.Module.doStart(Module.java:571)
 at org.eclipse.osgi.container.Module.start(Module.java:439)
 at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1582)
 at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1562)
 at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1533)
 at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1476)
 at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1)
 at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
 at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:340)
Caused by: javax.persistence.PersistenceException: No Persistence provider for EntityManager named test
 at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:61)
 at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
 at hibernateh2osgi.EntityManagerUtil.<clinit>(EntityManagerUtil.java:12)
 ... 18 more

!ENTRY org.eclipse.osgi 4 0 2015-05-11 09:22:16.239
!MESSAGE Bundle hibernateh2osgi_1.0.0.qualifier [36] is not active.

下面是带有依赖项的项目结构图:

我的 Manifest.MF 文件如下所示:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Hibernateh2osgi
Bundle-SymbolicName: hibernateh2osgi
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: hibernateh2osgi.Activator
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Meta-Persistence: META-INF/persistence.xml
Import-Package: javax.persistence;version="2.1.0",
 org.eclipse.core.runtime;version="3.4.0",
 org.h2;version="1.4.187",
 org.h2.jdbc;version="1.4.187",
 org.h2.jdbcx;version="1.4.187",
 org.h2.util;version="1.4.187",
 org.hibernate;version="4.3.9.Final",
 org.hibernate.annotations;version="4.3.9.Final",
 org.hibernate.ejb;version="4.3.9.Final",
 org.hibernate.osgi;version="4.3.9.Final",
 org.osgi.framework;version="1.8.0"

这是我的 persistence.xml

<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
  version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
  <persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
    <class>hibernateh2osgi.User</class>
    <class>hibernateh2osgi.Recipe</class>
    <properties>
      <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
      <!-- Creates the Database in the Projectfolder -->
      <property name="javax.persistence.jdbc.url"    value="jdbc:h2:./CookieAppDatabase" />
      <property name="javax.persistence.jdbc.user" value="sa" />
      <property name="javax.persistence.jdbc.password" value="" />
      <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
      <!-- creates Table if nessesary, otherwise just update it -->

      <property name="hibernate.hbm2ddl.auto" value="update" />
      <!-- creates the Table and Drops it after Restart
      <property name="hibernate.hbm2ddl.auto" value="create-drop" />
      -->
      <property name="show_sql" value="true"/>
      <property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
    </properties>
  </persistence-unit>
</persistence>

我试过这个,有没有指定要使用哪个持久性提供程序。

我看到了其他关于它的帖子,但我看不出我在那里做的错误。

这是来自激活器的代码。它只是启动 main 方法,因为我先用普通的 main 方法实现了它。

 public void start(BundleContext bundleContext) throws Exception {
  Activator.context = bundleContext;

  DataProviderImpl provider = new DataProviderImpl();
  provider.main();
 }

所以激活器启动这个:

public void main() {
  DataProviderImpl cookie = new DataProviderImpl();
  this.entityManager = EntityManagerUtil.getEntityManager();

  User mo = new User();
}

哪个应该调用测试持久性xml

public class EntityManagerUtil {
 private static final EntityManagerFactory entityManagerFactory;
 static {
  try {
   entityManagerFactory = Persistence
     .createEntityManagerFactory("test");

  } catch (Throwable ex) {
   System.err.println("Initial SessionFactory creation failed." + ex);
   throw new ExceptionInInitializerError(ex);
  }
 }

 public static EntityManager getEntityManager() {
  return entityManagerFactory.createEntityManager();

 }
}

设法让它与下面的提示一起工作。但是最后我决定改变EntityManager的获取方式。我是这样实现的

Bundle thisBundle = FrameworkUtil.getBundle( EntityManagerUtil.class );
// Could get this by wiring up OsgiTestBundleActivator as well.
BundleContext context = thisBundle.getBundleContext();
ServiceReference serviceReference = context.getServiceReference(PersistenceProvider.class.getName());
PersistenceProvider persistenceProvider = (PersistenceProvider) context.getService(serviceReference);
entityManagerFactory = persistenceProvider.createEntityManagerFactory( "test", null);
entityManagerFactory.createEntityManager();

因此您正在使用静态 Persistence.createEntityManagerFactory 创建 EntityManagerFactory。虽然我在 OSGi 的 jpa 提供程序规范中读到这应该可以工作,但我从未尝试过这种方式,并且不确定您必须提供什么才能使其工作。

我通常使用 Aries JPA 作为 OSGi jpa 提供程序规范的实现。它有助于为您的持久性单元创建 EntityMangerFactory 并将其作为服务提供。看这个例子:http://www.liquid-reality.de/x/C4DK