JBoss保险丝+JPA/Hibernate

JBoss Fuse +JPA/Hibernate

我在 JBoss Fuse 6.2 中有 OSGI 包,它导入带有实体和 dao classes 的 jar。
罐子包含:
Spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- Configures the Camel Context-->

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="
                http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

    <context:component-scan base-package="com.company"/>

    <tx:annotation-driven transaction-manager="transactionManager" />

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
        <property name="dataSource" ref="dataSource" />
        <property name="jpaDialect" ref="jpaDialect" />
    </bean>

    <bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

        <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
        <property name="persistenceUnitName" value="jpaData" />
        <property name="dataSource" ref="dataSource" />
        <property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
        <property name="jpaDialect" ref="jpaDialect" />
    </bean>

    <bean id="jpaVendorAdapter"
          class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <property name="database" value="POSTGRESQL" />
        <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
    </bean>

    <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />


    <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource"> 
        <property name="driverClass" value="org.postgresql.Driver" />  
        <property name="url" value="jdbc:postgresql://localhost:5432/MyDB" />
        <property name="username"  value="postgres" />       
        <property name="password"  value="123456" />        
    </bean> 
</beans>

persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
    xmlns="http://java.sun.com/xml/ns/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_1_0.xsd">


   <persistence-unit name="jpaData" transaction-type="RESOURCE_LOCAL" >
       <provider>org.hibernate.ejb.HibernatePersistence</provider>

       <class>com.company.model.entity.Entity</class>          

       <properties>
           <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
           <property name="hibernate.archive.autodetection" value="class"/>
           <property name="hibernate.show_sql" value="true"/>
           <property name="hibernate.format_sql" value="true"/>
           <property name="hbm2ddl.auto" value="update"/>
       </properties>
   </persistence-unit>
</persistence>

道class

@Repository
@Transactional
public class JpaEntityDao implements EntityDao {

    @PersistenceContext(unitName="jpaData")
    private EntityManager em;

    //methods that use EntityManager
}

实体class

@Entity
@Table(name="entity", schema="public")
public class Entity {
   //fields with setters and getters
}

我想在我的包中使用 JpaEntityDao。 我将 spring.xml 从 jar 导入到包的 spring xml

当我在 Karaf 中安装 bundle 时出现一些错误:

16:27:30,684 | ERROR | ExtenderThread-8 | ContextLoaderListener            | 174 - org.springframework.osgi.extender - 1.2.1 | Application context refresh failed (OsgiBundleXmlApplicationContext(bundle=myBundle, config=osgibundle:/META-INF/spring/*.xml))
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in URL [bundle://749.0:1/META-INF/spring/spring.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: jpaData] class or package not found
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1514)[167:org.apache.servicemix.bundles.spring-beans:3.2.12.RELEASE_1]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)[167:org.apache.servicemix.bundles.spring-beans:3.2.12.RELEASE_1]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)[167:org.apache.servicemix.bundles.spring-beans:3.2.12.RELEASE_1]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:293)[167:org.apache.servicemix.bundles.spring-beans:3.2.12.RELEASE_1]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)[167:org.apache.servicemix.bundles.spring-beans:3.2.12.RELEASE_1]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)[167:org.apache.servicemix.bundles.spring-beans:3.2.12.RELEASE_1]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:191)[167:org.apache.servicemix.bundles.spring-beans:3.2.12.RELEASE_1]
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1119)[169:org.apache.servicemix.bundles.spring-context:3.2.12.RELEASE_1]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:924)[169:org.apache.servicemix.bundles.spring-context:3.2.12.RELEASE_1]
    at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.access00(AbstractDelegatedExecutionApplicationContext.java:69)[173:org.springframework.osgi.core:1.2.1]
    at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.run(AbstractDelegatedExecutionApplicationContext.java:355)[173:org.springframework.osgi.core:1.2.1]
    at org.springframework.osgi.util.internal.PrivilegedUtils.executeWithCustomTCCL(PrivilegedUtils.java:85)[173:org.springframework.osgi.core:1.2.1]
    at org.springframework.osgi.context.support.AbstractDelegatedExecutionApplicationContext.completeRefresh(AbstractDelegatedExecutionApplicationContext.java:320)[173:org.springframework.osgi.core:1.2.1]
    at org.springframework.osgi.extender.internal.dependencies.startup.DependencyWaiterApplicationContextExecutor$CompleteRefreshTask.run(DependencyWaiterApplicationContextExecutor.java:132)[174:org.springframework.osgi.extender:1.2.1]
    at java.lang.Thread.run(Thread.java:745)[:1.8.0_65]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: jpaData] class or package not found
    at org.hibernate.ejb.Ejb3Configuration.addNamedAnnotatedClasses(Ejb3Configuration.java:1431)[668:org.hibernate.entitymanager:4.2.19.Final-redhat-1]
    at org.hibernate.ejb.Ejb3Configuration.addClassesToSessionFactory(Ejb3Configuration.java:1214)[668:org.hibernate.entitymanager:4.2.19.Final-redhat-1]
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:1058)[668:org.hibernate.entitymanager:4.2.19.Final-redhat-1]
    at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:703)[668:org.hibernate.entitymanager:4.2.19.Final-redhat-1]
    at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:75)[668:org.hibernate.entitymanager:4.2.19.Final-redhat-1]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:290)[716:org.apache.servicemix.bundles.spring-orm:3.2.12.RELEASE_1]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)[716:org.apache.servicemix.bundles.spring-orm:3.2.12.RELEASE_1]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1573)[167:org.apache.servicemix.bundles.spring-beans:3.2.12.RELEASE_1]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1511)[167:org.apache.servicemix.bundles.spring-beans:3.2.12.RELEASE_1]
    ... 14 more
Caused by: java.lang.ClassNotFoundException: com.company.model.Entity not found by org.hibernate.entitymanager [668]
    at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1556)[org.apache.felix.framework-4.4.1.jar:]
    at org.apache.felix.framework.BundleWiringImpl.access0(BundleWiringImpl.java:77)[org.apache.felix.framework-4.4.1.jar:]
    at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1993)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)[:1.8.0_65]
    at java.lang.Class.forName0(Native Method)[:1.8.0_65]
    at java.lang.Class.forName(Class.java:348)[:1.8.0_65]
    at org.hibernate.internal.util.ReflectHelper.classForName(ReflectHelper.java:170)[670:org.hibernate.core:4.2.19.Final-redhat-1]
    at org.hibernate.ejb.Ejb3Configuration.classForName(Ejb3Configuration.java:1348)[668:org.hibernate.entitymanager:4.2.19.Final-redhat-1]
    at org.hibernate.ejb.Ejb3Configuration.addNamedAnnotatedClasses(Ejb3Configuration.java:1420)[668:org.hibernate.entitymanager:4.2.19.Final-redhat-1]
    ... 22 more

Karaf 似乎在 persistence.xml 中找到了 class 定义,但无法加载实体 class。
欢迎提出任何建议。

看来 spring 是 osgi 的错误选择,并在那里得到证实 Using both Blueprint and Spring (Not spring-dm) with OSGi

所以用Apache Aries是很有必要的。你可以在那里找到工作示例 jpa+fuse https://github.com/pires/fabric8-persistence-hibernate
https://github.com/FuseByExample.

由于实体是从另一个 jar 导入并通过 EntityManager 由 bundle 加载的,您可能需要将 jar 构建为 bundle 并导出包,然后使用 `maven-bundle-plugin 导入包' 例如

罐子:

<plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <extensions>true</extensions>
    <configuration>
        <instructions>
            <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
            <Import-Package />
            <DynamicImport-Package>*</DynamicImport-Package>
            <Export-Package>com.company.model.*</Export-Package>
        </instructions>
    </configuration>
</plugin>

OSGi 捆绑包:

<plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <extensions>true</extensions>
    <configuration>
        <instructions>
            <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
            <Import-Package>com.company.model.entity</Import-Package>
            <DynamicImport-Package>*</DynamicImport-Package>
            <Export-Package />
        </instructions>
    </configuration>
</plugin>

您可以使用 packages:importspackages:exports 检查包导入、导出。最好创建一个功能来定义它所依赖的包。