【发布时间】:2015-06-29 08:04:28
【问题描述】:
在许多情况下,在 XML 文件中声明数据源和持久性单元并不理想。为此,我尝试使用 LocalContainerEntityManagerFactoryBean 配置 JPA。但首先,一些证明这种方法在非 OSGI 环境中有效的参考资料:
- www.baeldung.com/2011/12/22/the-persistence-layer-with-spring-data-jpa/
- docs.spring.io/spring/docs/current/spring-framework-reference/html/orm.html
为此,我整理的 Karaf OSGI 包的源代码如下。
public class AbstractXyzTableServiceImpl
{
private static EntityManagerFactory _entityManagerFactory;
MysqlDataSource mysqlDataSource = null;
// private static final SessionFactory configurationSessionFactory = buildConfigurationSessionFactory();
@Bean
public DataSource dataSource()
{
final MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setServerName("localhost");
dataSource.setDatabaseName("PSH");
dataSource.setUser("root");
dataSource.setPassword("password");
return dataSource;
}
@Bean
public Properties hibernateProperties()
{
final Properties properties = new Properties();
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.put("hibernate.connection.driver_class", "com.mysql.jdbc.Driver");
// properties.put("hibernate.connection.driver_class", "mysql-pool-xa");
// properties.put("hibernate.hbm2ddl.auto", "create-drop");
return properties;
}
public EntityManagerFactory getEntityManagerFactory()
{
// _entityManagerFactory = Persistence.createEntityManagerFactory("Config");
if (_entityManagerFactory == null)
_entityManagerFactory = getEntityManagerFactory(dataSource(), hibernateProperties());
return _entityManagerFactory;
}
@Bean
public EntityManagerFactory getEntityManagerFactory(DataSource dataSource, Properties hibernateProperties)
{
final LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
//emfBean.setPersistenceUnitName("Config");
emfBean.setDataSource(dataSource);
emfBean.setPackagesToScan(new String[] { "info.test.configuration.data" });
emfBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
emfBean.setJpaProperties(hibernateProperties);
emfBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
//emfBean.setPersistenceXmlLocation("META-INF/persistence.xml");
emfBean.afterPropertiesSet();
return emfBean.getObject();
}
}
不幸的是,Spring/LocalContainerEntityManagerFactoryBean 似乎坚持使用相应的 persistence.xml 文件,所有定义的属性都可能被覆盖。这很好,除了在 Karaf 4.0.0 中部署时我无法获取此代码来查找 persistence.xml 文件。 Karaf 提供的堆栈跟踪如下:
javax.persistence.PersistenceException: Unable to resolve persistence unit root URL
at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.determineDefaultPersistenceUnitRootUrl(DefaultPersistenceUnitManager.java:591)[158:org.apache.servicemix.bundles.spring-orm:4.1.6.RELEASE_1]
at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.preparePersistenceUnitInfos(DefaultPersistenceUnitManager.java:443)[158:org.apache.servicemix.bundles.spring-orm:4.1.6.RELEASE_1]
at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.afterPropertiesSet(DefaultPersistenceUnitManager.java:424)[158:org.apache.servicemix.bundles.spring-orm:4.1.6.RELEASE_1]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:310)[158:org.apache.servicemix.bundles.spring-orm:4.1.6.RELEASE_1]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)[158:org.apache.servicemix.bundles.spring-orm:4.1.6.RELEASE_1]
at info.leonard.configuration.service.impl.AbstractConfigurationServiceImpl.getEntityManagerFactory(AbstractConfigurationServiceImpl.java:83)[195:leonard-configuration-businessLogic:0.0.1.SNAPSHOT]
at info.leonard.configuration.service.impl.AbstractConfigurationServiceImpl.getEntityManagerFactory(AbstractConfigurationServiceImpl.java:67)[195:leonard-configuration-businessLogic:0.0.1.SNAPSHOT]
at info.leonard.configuration.service.impl.ConfigurationDomainServiceImpl.createDomain(ConfigurationDomainServiceImpl.java:80)[195:leonard-configuration-businessLogic:0.0.1.SNAPSHOT]
at info.leonard.configuration.command.domain.CreateDomainCommand.execute(CreateDomainCommand.java:34)[195:leonard-configuration-businessLogic:0.0.1.SNAPSHOT]
at org.apache.karaf.shell.commands.basic.AbstractCommand.execute(AbstractCommand.java:34)[43:org.apache.karaf.shell.core:4.0.0]
at org.apache.karaf.shell.compat.CommandTracker$1.execute(CommandTracker.java:109)[43:org.apache.karaf.shell.core:4.0.0]
at org.apache.karaf.shell.impl.console.osgi.secured.SecuredCommand.execute(SecuredCommand.java:67)[43:org.apache.karaf.shell.core:4.0.0]
at org.apache.karaf.shell.impl.console.osgi.secured.SecuredCommand.execute(SecuredCommand.java:87)[43:org.apache.karaf.shell.core:4.0.0]
at org.apache.felix.gogo.runtime.Closure.executeCmd(Closure.java:480)[43:org.apache.karaf.shell.core:4.0.0]
at org.apache.felix.gogo.runtime.Closure.executeStatement(Closure.java:406)[43:org.apache.karaf.shell.core:4.0.0]
at org.apache.felix.gogo.runtime.Pipe.run(Pipe.java:108)[43:org.apache.karaf.shell.core:4.0.0]
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:182)[43:org.apache.karaf.shell.core:4.0.0]
at org.apache.felix.gogo.runtime.Closure.execute(Closure.java:119)[43:org.apache.karaf.shell.core:4.0.0]
at org.apache.felix.gogo.runtime.CommandSessionImpl.execute(CommandSessionImpl.java:94)[43:org.apache.karaf.shell.core:4.0.0]
at org.apache.karaf.shell.impl.console.ConsoleSessionImpl.run(ConsoleSessionImpl.java:267)[43:org.apache.karaf.shell.core:4.0.0]
at java.lang.Thread.run(Thread.java:745)[:1.7.0_60-ea]
Caused by: java.io.FileNotFoundException: class path resource [] cannot be resolved to URL because it does not exist
at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:187)[155:org.apache.servicemix.bundles.spring-core:4.1.6.RELEASE_1]
at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.determineDefaultPersistenceUnitRootUrl(DefaultPersistenceUnitManager.java:588)[158:org.apache.servicemix.bundles.spring-orm:4.1.6.RELEASE_1]
... 20 more
在 Karaf 4.0.0 中,已加载以下弹簧功能:
@root()> feature:list | grep spring
spring | 4.1.6.RELEASE_1 | | Started | spring-4.0.0 | Spring 4.1.x support
spring-aspects | 4.1.6.RELEASE_1 | | Uninstalled | spring-4.0.0 | Spring 4.1.x AOP support
spring-instrument | 4.1.6.RELEASE_1 | | Uninstalled | spring-4.0.0 | Spring 4.1.x Instrument support
spring-jdbc | 4.1.6.RELEASE_1 | | Started | spring-4.0.0 | Spring 4.1.x JDBC support
spring-jms | 4.1.6.RELEASE_1 | | Uninstalled | spring-4.0.0 | Spring 4.1.x JMS support
spring-test | 4.1.6.RELEASE_1 | | Uninstalled | spring-4.0.0 | Spring 4.1.x Test support
spring-orm | 4.1.6.RELEASE_1 | x | Started | spring-4.0.0 | Spring 4.1.x ORM support
spring-oxm | 4.1.6.RELEASE_1 | | Uninstalled | spring-4.0.0 | Spring 4.1.x OXM support
spring-tx | 4.1.6.RELEASE_1 | | Started | spring-4.0.0 | Spring 4.1.x Transaction (TX) support
spring-web | 4.1.6.RELEASE_1 | | Uninstalled | spring-4.0.0 | Spring 4.1.x Web support
spring-web-portlet | 4.1.6.RELEASE_1 | | Uninstalled | spring-4.0.0 | Spring 4.1.x Web Portlet support
spring-websocket | 4.1.6.RELEASE_1 | | Uninstalled | spring-4.0.0 | Spring 4.1.x WebSocket support
spring-security | 3.1.4.RELEASE | | Uninstalled | spring-4.0.0 | Spring Security 3.1.x support
另外,我的pom.xml如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>info.leonard.configuration</groupId>
<artifactId>leonard-configuration-businessLogic</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>bundle</packaging>
<parent>
<groupId>info.leonard.configuration</groupId>
<artifactId>leonard-configuration</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../leonard-configuration</relativePath>
</parent>
<properties>
<log4j-version>1.2.16</log4j-version>
<slf4j-version>1.6.1</slf4j-version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Version>${project.version}</Bundle-Version>
<Import-Package>
org.apache.felix.service.command;version="[0.6,1)",
org.apache.felix.gogo.commands;version="[0.6,1)",
org.apache.karaf.shell.console;version="[2.2,4)",
com.mysql.jdbc,
org.hibernate,
org.hibernate.cfg,
org.hibernate.service,
org.hibernate.jpa,
org.hibernate.proxy,
org.hibernate.annotations,
org.springframework.context.annotation,
org.springframework.orm.jpa,
org.springframework.orm.jpa.vendor,
*,
javassist.util.proxy
info.leonard.foundation.common.*,
info.leonard.foundation.database.*,
info.leonard.foundation.environment.*,
info.leonard.foundation.exception.*,
info.leonard.foundation.finance.*,
info.leonard.foundation.finance.exception.*,
info.leonard.foundation.identity.*,
info.leonard.foundation.localization.*
</Import-Package>
<Export-Package>
info.leonard.configuration.data,
info.leonard.configuration.data.dao,
info.leonard.configuration.data.exception
</Export-Package>
<DynamicImport-Package>com.mysql.jdbc</DynamicImport-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
<version>4.0.0.M2</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.enterprise</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.1-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.6.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-osgi</artifactId>
<version>4.3.6.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.6.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.common</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>4.0.4.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j-version}</version>
</dependency>
<dependency>
<groupId>info.leonard.foundation</groupId>
<artifactId>leonard-foundation-businessLogic</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.servicemix.bundles</groupId>
<artifactId>org.apache.servicemix.bundles.commons-dbcp</artifactId>
<version>1.4_3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.0-beta1</version>
</dependency>
</dependencies>
</project>
这似乎是某种类路径问题:
- jira.spring.io/browse/SPR-8832
我的问题是:
- 有其他人在 Karaf/OSGI 中采用无 XML 方法来初始化 JPA,并且可以分享他们的方法
- 如果这是阻止 LocalContainerEntityManagerFactoryBean 在 resources/META-INF 目录中找到 persistence.xml 的类路径问题,是否有推荐的解决方案?
提前致谢, 兰迪
【问题讨论】:
-
不要使用
persistence.xml。您已将其配置为明确需要一个,不要,它应该在没有一个的情况下工作。此外,您的设置似乎相当复杂,为什么将其分配给静态字段并使用 get 方法公开它? -
感谢您的反馈。我已经注释掉了 setPersistenceUnitName() 和 setPersistenceXmlLocation() 的行,这是我最初的尝试。但我仍然遇到同样的问题。您是否建议进行任何其他更改?
-
我会先清理您的配置,因为这起初看起来很复杂。你自己管理bean回调(你不应该)你的getter我真的不明白为什么,你不应该将它分配给静态实例变量。只是想知道完整的堆栈跟踪我怀疑会有更多。我也不明白为什么到底是一个配置类扩展了一个名为
AbstractDao的类??? -
再次感谢您的反馈,一些 cmets。该实体被称为配置,但它可以被称为任何东西。它只是一个数据库表,所以让我们将其重命名为 XyzTable,这样我们就不会被挂断。至于 AbstractDao 超类,我将完全删除超类调用,它没有被使用(我只是从工作的 Karaf 代码中复制代码来测试 LocalContainerEntityManagerFactoryBean)。至于回调,我在任何地方都没有看到,所以也许需要澄清一下?堆栈跟踪是 Karaf 提供的所有内容。
-
但归根结底,问题在于第一次调用 getEntityManagerFactory(),它试图实例化 LocalContainerEntityManagerFactoryBean 的实例。不管其他上下文如何,似乎在 Karaf 之外找到的代码在 Karaf 中不起作用......因为代码坚持寻找一个 persistence.xml 文件。不确定这是否是一个 Karaf 问题:jira.spring.io/browse/SPR-8832。或者,如果有其他事情在起作用。
标签: spring hibernate jpa karaf