JPA使用备用的"persistence.xml"

21

我知道使用以下指令:

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

JPA持久化机制会读取名为"persistence.xml"的文件,查找名为"persistence-unit-name"的持久化单元,并基于其构建EntityManagerFactory。

我的问题是,我如何强制JPA使用一个不同于"persistence.xml"的文件?例如,"persistence-test.xml"。


1
因为我想为我的测试使用另一个persistence.xml。 - Mr.Eddart
3
你可以在同一个 persistence.xml 文件中拥有多个持久化单元,并在测试中使用相应的单元。 - Giorgos Dimtsas
我遇到了一些Maven中的错误,有时(随机地)在测试期间选择了错误的persistence.xml文件。 - Wojciech Owczarczyk
6个回答

20

目前没有JPA标准的方法来实现这一点,尽管各个JPA提供者可能会提供一种方法。我建议使用标准的方法为主要和测试设置不同的类路径。

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

如果需要更高级的逻辑,请考虑使用Spring的JPA支持。它将使您能够处理高级情况,例如集成多个persistence.xml文件


只有在运行“mvn test”命令时,才会使用src/test/resources中的persistence.xml文件。一旦你运行“mvn install”,你的测试也会被运行,并且该文件将从src/main/resources中获取,这会导致问题。 - Alexandr
@Alexandr,这不是Maven的工作方式。当您触发生命周期阶段时,将执行该阶段及其之前的所有阶段。测试阶段的执行完全相同,无论您是使用test还是install启动Maven。请参见https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html。 - Sean Patrick Floyd

15

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

Properties pros = new Properties();

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


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

4

2

我们希望拥有两个单独的文件。一个应该只被生产配置读取,另一个用于测试。这个想法是重命名或隐藏生产文件。

War解决方案

不要将放在中。而是将其放入中。这是文件应该放置的位置,在此处它不会被测试程序看到。

这个解决方案在Gradle环境下适用于我,但我希望它也能适用于其他环境。

Jar解决方案

将生产文件命名为。现在我们已经完成了测试配置。对于生产,我们必须进行一些处理。每个环境可能都有自己的方式,这就是我在Gradle中的做法:

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

在我的应用程序中,persistence.xml文件仅在部署时,即在jar / war包中才是必需的。而且这些都是唯一可见此文件的地方。如果没有双重的persistence,我将无法启动我的数据库。主要原因是使用了jta-data-source,另一个原因是使用了2个不同命名的持久化单元。


你救了我的命!我已经为这个问题苦苦挣扎了一个星期,如果没有看到你的答案,天知道我还要挣扎多久。在我将“test” persistence.xml 移动到 src\main\webapp\WEB-INF\classes\META-INF\ 后,它对我起了魔法般的作用。非常非常非常感谢你! - Arthur Eirich

1

1
您可以在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());
}

现在,不要忘记在那些处理数据库的方法上使用@Transactional注释。
最后,请不要忘记在您的存储库中注入EntityManager(此存储库类应该在其上具有@Repository注释)。

如果您需要在生产服务器上使用jtaDataSource,那么我不确定这是否有效。然后您需要使用persistence.xml文件,Hibernate会找到它并进行处理,在测试期间。 - Jarekczek

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