web-dev-qa-db-ja.com

代替の「persistence.xml」を使用するJPA

私は命令でそれを知っています:

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

JPA永続化メカニズムは「persistence.xml」ファイルを読み取り、「persistence-unit-name」という永続性ユニットを探し、それに基づいてEntityManagerFactoryを構築します。

私の質問は、JPAをどのように強制することができますか"persistence.xml"とは異なるファイルを取得 ??たとえば、「persistence-test.xml」。

21
Mr.Eddart

これを行うための標準化されたJPA方法はありませんが、個々のJPAプロバイダーが方法を提供する場合があります。メインとテストで異なるクラスパスを使用する標準的な方法を提案します。

たとえば、Mavenを使用していて、2つのMETA-INF/persistence.xmlファイルがあり、1つはsrc/main/resourcesに、もう1つはsrc/test/resourcesにある場合、テストはsrc/test/resourcesにあるファイルを取得します。クラスパス内のメインクラス/リソースの前にテストクラス/リソースを置きます。同様の方法で動作するようにAntを簡単に構成できます。

より高度なロジックが必要な場合は、 SpringのJPAサポート の使用を検討してください。 複数のpersistence.xmlファイルの統合 などの高度な状況に対処できます。

20

EclipseLinkでは、次のことができます。

Properties pros = new Properties();

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


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

できないと思います。これを行う長い方法は次のとおりです。

4
Buhake Sindi

したがって、2つの別々のpersistence.xmlファイルが必要です。 1つは実稼働構成でのみ読み取り、もう1つはテストで読み取る必要があります。アイデアはプロダクションの名前変更または非表示ファイルです。

戦争解

persistence.xmlsrc\main\resources\META-INF\に含めないでください。代わりにsrc\main\webapp\WEB-INF\classes\META-INF\に入れてください。これはファイルが存在する場所であり、この場所ではテストからは見えません。

このソリューションは私にとってGradle環境で機能しますが、他のソリューションでも機能することを期待しています。

Jarソリューション

製品ファイルの名前をpersistence-ee.xmlに変更します。これでテスト構成が完了しました。生産のために、我々はいくつかの処理を採用しなければなりません。それぞれの環境には独自の方法があるかもしれません、それが私がgradleでそれをする方法です:

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

私のアプリケーションでは、プロダクション用のpersistence.xmlファイルはデプロイメント時にのみ必要です。つまり、jar/warパッケージにあります。そして、これらはこのファイルが表示される唯一の場所です。ダブルpersistenceがないと、データベースを起動できませんでした。主な理由はjta-data-sourceを使用することでした。もう1つは、2つの個別の名前付き永続化ユニットです。

2
Jarekczek

OpenEJBを使用してテストを実行している場合、希望するJPAプロバイダーを使用して、希望どおりの操作を実行できます。ここで同様の質問と関連する回答:

mavenにmain/resources/persistence.xmlを無視してtest/...を優先するように指示する方法

1
David Blevins

次のように、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を使用していないので、データソースを設定する上記のメソッドで指定したDataSourceを返すBeanを作成する必要があります。

@Bean
public DataSource springJpaDataSource()
{
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl("jdbc:mysql://localhost/SpringJpa");
dataSource.setUsername("tomcatUser");
dataSource.setPassword("password1234");
return dataSource;
}

次に、この構成ファイルに対して@EnableTransactionManagementアノテーションを使用します。次に、そのアノテーションを配置するときに、最後のBeanを1つ作成する必要があります。

@Bean
public PlatformTransactionManager jpaTransactionManager()
{
return new JpaTransactionManager(
this.entityManagerFactoryBean().getObject());
}

ここで、DBを処理するメソッドに対して@Transactionalアノテーションを使用することを忘れないでください。

最後に、リポジトリにEntityManagerを注入することを忘れないでください(このリポジトリクラスには@Repositoryアノテーションが必要です)。

1
Faraz