在SE环境中将JPA实体jar与persistence.xml解耦

13

有没有一种方法可以在多个SE应用程序中重复使用带有JPA注释的jar文件(作为依赖项)?由于在SE环境中不支持persistence.xml中的<jar-file>,因此是否还有其他方法?

有没有办法在多个SE应用程序中重复使用带有JPA注释的jar文件(作为依赖项)?由于在SE环境中不支持persistence.xml中的<jar-file>,因此是否还有其他方法?
4个回答

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 文件中完全枚举要管理的实体类和类集。

现在,如果你不介意不可移植性的话,Hibernate 支持 在Java SE 中使用jar-file元素(这种情况下需要绝对URL,不方便)。Hibernate实际上也支持自动检测,甚至在JSE中也是如此。更好的是:
<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>

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

根据我的经验 - 它现在运行正常。

我们使用的是: Hibernate3.jar 3.6.0.Final hibernate-jpa-2.0-api-1.0.0.Final.jar

< jar-file >file:...< /jar-file > 知道如何查找相对路径 - 它既适用于 jar 文件,也适用于目录。

我使用这种能力两次:

  • 使用包含实体的 Jar - 该 Jar 在多个应用程序中都被使用。每个应用程序都有自己的 persistence.xml - 主要是为了提供不同的 ehcache 设置。
  • 在 Junits 中使用时,当我希望所有其他依赖项目中的测试都有一个单独的 persistence.xml 文件,该文件将指向实体项目中的所有实体时。然后我们将持久性文件保留在实体项目的 test/resources/META-INF 下,指向该项目的 Bin 目录: < jar-file >file:../entities/bin< /jar-file >

1

我遇到了一个问题。稍微有些扭曲,因为我需要独立运行几个jar文件以及作为war部署的一部分。

有一些黑客方法似乎都围绕着多个persistence.xml文件和/或尝试使用Spring资源加载器引用jar文件的一些奇怪尝试(对我来说并没有起作用)。

我的个人黑客方法是使用Spring资源加载器解析出所有实体jar中都有的资源的URL jar引用,并使用Spring持久性单元管理器将它们注入虚拟persistence.xml中的jar-file标记中。

这是一个迂回的方法,但避免了使用多个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('!'));
}

还有Spring上下文相关的东西:

<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>

你最好过滤掉 jar 包的名称 - 第三方的 jar 包可能包含任何内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接