在许多情况下,声明XML文件中的数据源和持久性单元并不理想。为此,我尝试使用LocalContainerEntityManagerFactoryBean配置JPA。但首先,一些证明此方法的参考资料适用于非OSGI环境:
为此,我的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>
这似乎是某种类别的类路径问题:
我的问题是:
提前致谢, 好色
答案 0 :(得分:0)
对于初学者,我会尝试将您的配置更改为以下内容。
public class AbstractConfigurationServiceImpl extends AbstractDao {
@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 FactoryBean<EntityManagerFactory> entityManagerFactory()
{
final LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
emfBean.setDataSource(dataSource());
emfBean.setPackagesToScan(new String[] { "info.test.configuration.data" });
emfBean.setJpaVendorAdapter(hibernateJpaVendorAdapter());
return emfBean;
}
@Bean
public JpaVendorAdapter hibernateJpaVendorAdapter(){
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setDatabasePlatform("org.hibernate.dialect.MySQL5InnoDBDialect"
return jpaVendorAdapter;
}
}
您实际上并不需要这些属性,因此您不需要设置JpaDialect
,因为您已经设置了JpaVendorAdapter
。您还应该让Spring管理生命周期,而不是自己。
有一件事我想知道为什么它在延伸AbstractDao
,对我来说,看起来你正在将DAO方法转变为配置appraoch。基本上混合了关注点和责任。这也基于您的堆栈跟踪。
在您的服务中,您应该申请EntityManager
而不是EntityManagerFactory
。如果你真的想要注入它但不使用配置类作为基类。
@Service
@Transactional
public class ConfigurationDomainServiceImpl implements ConfigurationDomainService {
@PersistenceContext
private EntityManager em;
public void createDomain(...) {
Domain d = // do whatever is needed to create the domain.
em.persist(domain);
}
}