在SE环境中将JPA实体jar与persistence.xml分离

时间:2010-04-12 13:34:52

标签: java hibernate orm jpa code-reuse

有没有办法在多个SE应用程序中重用带有JPA注释实体的jar(作为依赖项)? < JAR-文件>在SE环境中不支持persistence.xml,那么还有另一种方法吗?

4 个答案:

答案 0 :(得分:6)

正式(按规格),您必须使用class元素指定所有类。引用JSR-220 6.2.1.6 mapping-file,jar-file,class,exclude-unlisted-classes 一章:

  

也可以指定命名的托管持久性类列表,而不是JAR文件和映射文件。将处理在这些类上找到的任何映射元数据注释,或者使用映射注释默认值映射它们。 class元素用于列出托管持久性类。 必须在Java SE环境中指定所有命名的托管持久性类的列表,以确保可移植性。可移植Java SE应用程序不应依赖此处描述的其他机制来指定持久性单元的托管持久性类。持久性提供程序还可能要求必须在Java SE环境中的每个persistence.xml文件中完全枚举要管理的实体类和类集。

现在,如果你不介意不可移植,那么在Java SE中使用jar-file元素的Hibernate supports(在这种情况下需要一个绝对的url,而不是方便)。即使在JSE中,Hibernate实际上也支持自动检测。好多了:

<persistence 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"
  version="1.0">
  <persistence-unit name="foo">

    <!-- This is required to be spec compliant, Hibernate however supports auto-detection even in JSE. -->
    <class>foo.Bar<class>

    <properties>
      <!-- Scan for annotated classes and Hibernate mapping XML files -->
      <property name="hibernate.archive.autodetection" value="class, hbm"/>
      ...
    </properties>
  </persistence-unit>

</persistence>

答案 1 :(得分:2)

据我所知,没有办法让类扫描注释在该配置中工作。但是,您可以在每个实体类中明确指出persistence.xml文件。

<persistence 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"
                     version="1.0">

  <persistence-unit name="punit">

    <provider>org.hibernate.ejb.HibernatePersistence</provider>

    <jta-data-source>java:/myDS</jta-data-source>

    <!-- Must be explicit as classes are in separate jar -->
    <class>com.foo.Bar</class>
    <class>com.foo.Baz</class>

    <properties/>      
  </persistence-unit>

</persistence>

答案 2 :(得分:2)

根据我的经验 - 它现在有效。

我们正在使用: Hibernate3.jar 3.6.0.Final 冬眠-JPA-2.0-API-1.0.0.Final.jar

&lt; jar文件&gt;文件:...&lt; / jar-file&gt; 知道如何查找相对路径 - 它适用于jar文件或目录。

我两次使用此能力:

  • 持有我的实体的Jar - 用于多个应用程序。每个应用程序都有自己的persistence.xml - 主要用于提供不同的ehcache设置。
  • 使用Junits,当我想要所有测试时,在所有其他依赖项目中都有一个指向实体项目中所有实体的persistence.xml文件。然后我们将persistence.xml保存在test / resources / META-INF下的实体项目中,指向该项目的Bin目录: 的&LT; jar文件&gt;文件:../ entities / bin&lt; / jar-file&gt;

答案 3 :(得分:1)

这是我遇到的一个问题。因为我需要独立运行几个jar以及战争部署的一部分,所以稍微有点正面。

有一些hacks似乎围绕着多个persistence.xml文件和/或一些奇怪的尝试尝试使用spring资源加载器引用jar文件(这对我不起作用)。

我的个人攻击是使用spring资源加载器来解析所有实体jar中的资源,解析URL jar引用并使用Spring持久性单元管理器将这些注入到虚拟持久化中的jar-file标记中.XML

这是一种全面的方式,但避免使用多个persistence.xml - 这在技术上是无效的。

public class SpringPersistenceUnitManager extends DefaultPersistenceUnitManager implements ApplicationContextAware {

private final Logger log = LoggerFactory.getLogger(getClass());

private ApplicationContext ctx = null;


private String jarLocationPattern;

@Override
protected void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {
    super.postProcessPersistenceUnitInfo(pui);
    try {
        Resource[] resources = ctx.getResources("classpath*:applicationContext.xml");
        for (Resource res : resources) {
            String resJar = resolveJar(res.getURL());
            if (!resJar.equals(pui.getPersistenceUnitRootUrl().toString())) {
                log.info("Adding " + resJar + " to persistence context");
                pui.addJarFileUrl(new URL(resJar));
            }
        }
    }
    catch (IOException e) {
        log.error("error", e);
    }
}

private String resolveJar(URL fileInJar) {
    String path = fileInJar.getPath();
    return path.substring(0, path.indexOf('!'));
}

和春天语境:

                                   

<util:properties id="hibernate.properties" location="classpath:hibernate.properties" />

<bean id="persistenceUnitManager" class="com.rokksoft.blackice.util.SpringPersistenceUnitManager"
    p:defaultDataSource-ref="jdbcDataSourcePool"
/>

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" lazy-init="true"
    p:persistenceUnitManager-ref="persistenceUnitManager"
    p:persistenceUnitName="blackicePU"
    p:dataSource-ref="jdbcDataSourcePool"
    p:jpaProperties-ref="hibernate.properties">
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
    </property>
</bean>

你想要理想地过滤罐子名称 - 第三方罐子可以有任何东西。