JPA 使用替代“persistence.xml”

Posted

技术标签:

【中文标题】JPA 使用替代“persistence.xml”【英文标题】:JPA using alternative "persistence.xml" 【发布时间】:2011-11-05 20:50:59 【问题描述】:

我知道有说明:

Persistence.createEntityManagerFactory("persistence-unit-name");

JPA持久化机制读取“persistence.xml”文件,寻找名为“persistence-unit-name”的持久化单元,并基于它构造EntityManagerFactory。

我的问题是,如何强制 JPA 获取与“persistence.xml”不同的文件?例如,“persistence-test.xml”。

【问题讨论】:

因为我想使用替代的 persistence.xml 进行测试。 @edutesoy 您可以在同一个 persistence.xml 文件中拥有多个持久性单元,并在测试中使用适当的一个。 我在 Maven 中遇到了一些错误,有时(随机)在测试期间选择了错误的 persistence.xml 文件。 【参考方案1】:

没有标准化的 JPA 方法来执行此操作,尽管个别 JPA 提供者可能会提供一种方法。我建议使用标准方法为 main 和 test 设置不同的类路径。

例如,如果您使用 Maven,并且您有两个 META-INF/persistence.xml 文件,一个在 src/main/resources 中,一个在 src/test/resources 中,测试将选择 src/test/resources 中的一个,因为 Maven 放置了测试类/资源在类路径中的主要类/资源之前。您可以轻松地将 Ant 配置为以类似的方式工作。

如果您需要更高级的逻辑,请考虑使用Spring's JPA support。它会让你处理像integrating multiple persistence.xml files这样的高级情况。

【讨论】:

persistence.xml 文件仅在我运行 mvn test 命令时才从 src/test/resources 使用。一旦你运行 mvn install,你的测试也会运行,并且文件是从 src/main/resources 中获取的,这会导致问题。 @Alexandr 这不是 Maven 的工作方式。当您触发生命周期阶段时,将执行直到并包括该阶段的所有阶段。测试阶段的执行是完全一样的,与你启动 Maven 是用 test 还是 install 无关。见maven.apache.org/guides/introduction/…【参考方案2】:

在 EclipseLink 中,您可以执行以下操作:

Properties pros = new Properties();

pros.setProperty(PersistenceUnitProperties.ECLIPSELINK_PERSISTENCE_XML, 
                 "META-INF/persistence-alternative.xml");


EntityManagerFactory factory = 
    Persistence.createEntityManagerFactory("pu-name", pros);

【讨论】:

【参考方案3】:

我不认为你可以。这样做的漫长方法是:

创建一个工厂,它将读取您的 persistence-test.xml 并呈现 Map<String, String> 属性,并且。 致电Persistence.createEntityManagerFactory(persistenceUnitName, Map properties)。这样,它从 properties 映射读取,而不是从 persistence.xml 读取。

【讨论】:

【参考方案4】:

所以我们想要有 2 个独立的 persistence.xml 文件。一个只能由生产配置读取,另一个用于测试。这个想法是重命名或隐藏生产文件。

战争解决方案

不要将persistence.xml 放入src\main\resources\META-INF\。而是将其放入src\main\webapp\WEB-INF\classes\META-INF\。那是文件应该在的位置,在这个位置它不会被测试看到。

此解决方案在 gradle 环境中适用于我,但我希望其他人也可以。

罐子解决方案

将生产文件重命名为persistence-ee.xml。现在我们完成了测试配置。为了生产,我们必须采用一些加工。每个环境可能都有自己的方式,我在 gradle 中就是这样做的:

tasks.withType(Jar) 
  rename  fileName ->
    fileName == "persistence-ee.xml" ? "persistence.xml" : fileName;
  

在我的应用程序中,只有在部署时才需要使用 persistence.xml 文件进行生产,即在 jar/war 包中。这些是该文件可见的唯一地方。没有双 persistence 我无法启动我的数据库。主要原因是使用jta-data-source,另一个:2 个独立的命名持久单元。

【讨论】:

你救了我的命!我已经为这个问题苦苦挣扎了一个星期,上帝只知道如果我没有看到你的答案,我会苦苦挣扎多久。在我将“测试”persistence.xml 移动到“src\main\webapp\WEB-INF\classes\META-INF”之后,它对我很有用。非常非常非常感谢!【参考方案5】:

如果您使用 OpenEJB 来驱动您的测试,那么您可以使用任何您想要的 JPA 提供程序来做您想做的事。类似的问题和相关答案在这里:

How to instruct Maven to ignore my main/resources/persistence.xml in favor of test/...?

【讨论】:

【参考方案6】:

你可以像这样在 Spring 中完全不使用 persistence.xml 来配置 Hibernate:

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean()

Map<String, Object> properties = new Hashtable<>();
properties.put("javax.persistence.schema-generation.database.action",
"none");
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabasePlatform("org.hibernate.dialect.mysql5InnoDBDialect"); //you can change this if you have a different DB
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(adapter);
factory.setDataSource(this.springJpaDataSource());
factory.setPackagesToScan("package name");
factory.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
factory.setValidationMode(ValidationMode.NONE);
factory.setJpaPropertyMap(properties);
return factory;

由于你没有使用persistence.xml,你应该创建一个bean,它返回你在上面设置数据源的方法中指定的DataSource:

@Bean
public DataSource springJpaDataSource()

DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:mysql://localhost/SpringJpa");
dataSource.setUsername("tomcatUser");
dataSource.setPassword("password1234");
return dataSource;

然后你在这个配置文件上使用@EnableTransactionManagement注解。现在,当您添加该注释时,您必须创建最后一个 bean:

@Bean
public PlatformTransactionManager jpaTransactionManager()

return new JpaTransactionManager(
this.entityManagerFactoryBean().getObject());

现在,不要忘记在那些处理 DB 的方法上使用 @Transactional 注释。

最后,不要忘记在你的存储库中注入EntityManager(这个存储库类应该有@Repository 注释)。

【讨论】:

如果您需要在生产服务器上使用 jtaDataSource,我不会这样做。然后你需要persistence.xml,hibernate会在测试期间找到并处理它。

以上是关于JPA 使用替代“persistence.xml”的主要内容,如果未能解决你的问题,请参考以下文章

如何为 JPA 和 Hibernate 创建一个 persistence.xml 文件?

Jpa 的Persistence.xml配置讲解

JPA的配置文件persistence.xml参数详解

JAVA JPA persistence.xml - 如何在我的应用程序中使用之前测试连接有效性

EJB,JPA persistence.xml问题Wildfly 8.2 intellij

Jpa规范中persistence.xml 配置文件解析