persistence.xml 構成ファイルを使用せずに JPA EntityManager を作成する
-
22-09-2019 - |
質問
初期化する方法はありますか EntityManager
永続化ユニットが定義されていないのですか?エンティティ マネージャーを作成するために必要なプロパティをすべて指定できますか?を作成する必要があります EntityManager
実行時にユーザーが指定した値から。を更新しています persistence.xml
再コンパイルはオプションではありません。
これを行う方法に関するアイデアは大歓迎です。
解決
初期化する方法はありますか
EntityManager
永続化ユニットが定義されていないのですか?
定義する必要があります 少なくとも 1 つの永続ユニット persistence.xml
デプロイメント記述子。
を作成するために必要なプロパティをすべて指定できますか?
Entitymanager
?
- name 属性は必須です。他の属性と要素はオプションです。(JPA仕様)。したがって、これは多かれ少なかれ最小値になるはずです
persistence.xml
ファイル:
<persistence>
<persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
SOME_PROPERTIES
</persistence-unit>
</persistence>
Java EE環境では、
jta-data-source
そしてnon-jta-data-source
要素は指定するために使用されます JTA および/または非 JTA データ ソースのグローバル JNDI 名 永続化プロバイダーによって使用されます。
したがって、ターゲット アプリケーション サーバーが JTA (JBoss、Websphere、GlassFish) をサポートしている場合、 persistence.xml
次のようになります:
<persistence>
<persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
<!--GLOBAL_JNDI_GOES_HERE-->
<jta-data-source>jdbc/myDS</jta-data-source>
</persistence-unit>
</persistence>
ターゲット アプリケーション サーバーが JTA (Tomcat) をサポートしていない場合、 persistence.xml
次のようになります:
<persistence>
<persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
<!--GLOBAL_JNDI_GOES_HERE-->
<non-jta-data-source>jdbc/myDS</non-jta-data-source>
</persistence-unit>
</persistence>
データ ソースがグローバル JNDI (たとえば、Java EE コンテナの外部) にバインドされていない場合は、通常、JPA プロバイダー、ドライバー、URL、ユーザー、およびパスワードのプロパティを定義します。 しかし プロパティ名はJPAプロバイダーによって異なります。したがって、JPA プロバイダーとしての Hibernate の場合、 persistence.xml
ファイルは次のようになります:
<persistence>
<persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>br.com.persistence.SomeClass</class>
<properties>
<property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.ClientDriver"/>
<property name="hibernate.connection.url" value="jdbc:derby://localhost:1527/EmpServDB;create=true"/>
<property name="hibernate.connection.username" value="APP"/>
<property name="hibernate.connection.password" value="APP"/>
</properties>
</persistence-unit>
</persistence>
トランザクションタイプ属性
一般に、Java EE 環境では、トランザクション タイプは
RESOURCE_LOCAL
非 JTA データソースが提供されることを前提としています。Java EE 環境では、この要素が指定されていない場合、デフォルトは JTA です。Java SE 環境では、この要素が指定されていない場合、デフォルトのRESOURCE_LOCAL
と推測されるかもしれない。
- Java SE アプリケーションの移植性を確保するには、 明示的に列挙する必要がある 永続化ユニットに含まれる管理された永続化クラス (JPA 仕様)
を作成する必要があります
EntityManager
実行時にユーザーが指定した値から
したがって、これを使用します:
Map addedOrOverridenProperties = new HashMap();
// Let's suppose we are using Hibernate as JPA provider
addedOrOverridenProperties.put("hibernate.show_sql", true);
Persistence.createEntityManagerFactory(<PERSISTENCE_UNIT_NAME_GOES_HERE>, addedOrOverridenProperties);
他のヒント
はい、あなた@Configurationクラス(またはその同等のスプリング設定XML)内でこのように春を使用して、任意のXMLファイルを使用せずにすることができます:
@Bean
public LocalContainerEntityManagerFactoryBean emf(){
properties.put("javax.persistence.jdbc.driver", dbDriverClassName);
properties.put("javax.persistence.jdbc.url", dbConnectionURL);
properties.put("javax.persistence.jdbc.user", dbUser); //if needed
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setPersistenceProviderClass(org.eclipse.persistence.jpa.PersistenceProvider.class); //If your using eclipse or change it to whatever you're using
emf.setPackagesToScan("com.yourpkg"); //The packages to search for Entities, line required to avoid looking into the persistence.xml
emf.setPersistenceUnitName(SysConstants.SysConfigPU);
emf.setJpaPropertyMap(properties);
emf.setLoadTimeWeaver(new ReflectiveLoadTimeWeaver()); //required unless you know what your doing
return emf;
}
を作成することができました EntityManager
Hibernate と PostgreSQL を純粋に Java コードを使用して (Spring 構成で) 使用すると、次のようになります。
@Bean
public DataSource dataSource() {
final PGSimpleDataSource dataSource = new PGSimpleDataSource();
dataSource.setDatabaseName( "mytestdb" );
dataSource.setUser( "myuser" );
dataSource.setPassword("mypass");
return dataSource;
}
@Bean
public Properties hibernateProperties(){
final Properties properties = new Properties();
properties.put( "hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect" );
properties.put( "hibernate.connection.driver_class", "org.postgresql.Driver" );
properties.put( "hibernate.hbm2ddl.auto", "create-drop" );
return properties;
}
@Bean
public EntityManagerFactory entityManagerFactory( DataSource dataSource, Properties hibernateProperties ){
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource( dataSource );
em.setPackagesToScan( "net.initech.domain" );
em.setJpaVendorAdapter( new HibernateJpaVendorAdapter() );
em.setJpaProperties( hibernateProperties );
em.setPersistenceUnitName( "mytestdomain" );
em.setPersistenceProviderClass(HibernatePersistenceProvider.class);
em.afterPropertiesSet();
return em.getObject();
}
への呼び出し LocalContainerEntityManagerFactoryBean.afterPropertiesSet()
は 不可欠 そうしないと工場は決して建設されないので、 getObject()
戻り値 null
そしてあなたは追いかけています NullPointerException
一日中です。>:-(
次に、次のコードで動作しました。
PageEntry pe = new PageEntry();
pe.setLinkName( "Google" );
pe.setLinkDestination( new URL( "http://www.google.com" ) );
EntityTransaction entTrans = entityManager.getTransaction();
entTrans.begin();
entityManager.persist( pe );
entTrans.commit();
私のエンティティは次のとおりです。
@Entity
@Table(name = "page_entries")
public class PageEntry {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String linkName;
private URL linkDestination;
// gets & setters omitted
}
ここでは春のないソリューションです。
定数はorg.hibernate.cfg.AvailableSettings
から取得されます:
entityManagerFactory = new HibernatePersistenceProvider().createContainerEntityManagerFactory(
archiverPersistenceUnitInfo(),
ImmutableMap.<String, Object>builder()
.put(JPA_JDBC_DRIVER, JDBC_DRIVER)
.put(JPA_JDBC_URL, JDBC_URL)
.put(DIALECT, Oracle12cDialect.class)
.put(HBM2DDL_AUTO, CREATE)
.put(SHOW_SQL, false)
.put(QUERY_STARTUP_CHECKING, false)
.put(GENERATE_STATISTICS, false)
.put(USE_REFLECTION_OPTIMIZER, false)
.put(USE_SECOND_LEVEL_CACHE, false)
.put(USE_QUERY_CACHE, false)
.put(USE_STRUCTURED_CACHE, false)
.put(STATEMENT_BATCH_SIZE, 20)
.build());
entityManager = entityManagerFactory.createEntityManager();
そして悪名高いPersistenceUnitInfo
private static PersistenceUnitInfo archiverPersistenceUnitInfo() {
return new PersistenceUnitInfo() {
@Override
public String getPersistenceUnitName() {
return "ApplicationPersistenceUnit";
}
@Override
public String getPersistenceProviderClassName() {
return "org.hibernate.jpa.HibernatePersistenceProvider";
}
@Override
public PersistenceUnitTransactionType getTransactionType() {
return PersistenceUnitTransactionType.RESOURCE_LOCAL;
}
@Override
public DataSource getJtaDataSource() {
return null;
}
@Override
public DataSource getNonJtaDataSource() {
return null;
}
@Override
public List<String> getMappingFileNames() {
return Collections.emptyList();
}
@Override
public List<URL> getJarFileUrls() {
try {
return Collections.list(this.getClass()
.getClassLoader()
.getResources(""));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
@Override
public URL getPersistenceUnitRootUrl() {
return null;
}
@Override
public List<String> getManagedClassNames() {
return Collections.emptyList();
}
@Override
public boolean excludeUnlistedClasses() {
return false;
}
@Override
public SharedCacheMode getSharedCacheMode() {
return null;
}
@Override
public ValidationMode getValidationMode() {
return null;
}
@Override
public Properties getProperties() {
return new Properties();
}
@Override
public String getPersistenceXMLSchemaVersion() {
return null;
}
@Override
public ClassLoader getClassLoader() {
return null;
}
@Override
public void addTransformer(ClassTransformer transformer) {
}
@Override
public ClassLoader getNewTempClassLoader() {
return null;
}
};
}
プレーン JPA を使用すると、 PersistenceProvider
実装 (例:休止状態)、使用できます PersistenceProvider#createContainerEntityManagerFactory(PersistenceUnitInfo情報、Mapマップ) をブートストラップするメソッド EntityManagerFactory
を必要とせずに persistence.xml
.
ただし、実装する必要があるのは面倒です。 PersistenceUnitInfo
したがって、両方ともブートストラップ JPA をサポートする Spring または Hibernate を使用することをお勧めします。 persistence.xml
ファイル:
this.nativeEntityManagerFactory = provider.createContainerEntityManagerFactory(
this.persistenceUnitInfo,
getJpaPropertyMap()
);
どこ 永続化ユニット情報 Spring 固有のメソッドによって実装されます。 MutablePersistenceUnitInfo クラス。
チェックアウト この記事 Hibernate を使用してこの目標を達成する方法を示す優れたデモンストレーションです。
私が使用している DataNucleus JPA にもこれを行う方法があります そのドキュメントの中で. 。Spring や醜い実装は必要ありません。 PersistenceUnitInfo
.
次のようにするだけです
import org.datanucleus.metadata.PersistenceUnitMetaData;
import org.datanucleus.api.jpa.JPAEntityManagerFactory;
PersistenceUnitMetaData pumd = new PersistenceUnitMetaData("dynamic-unit", "RESOURCE_LOCAL", null);
pumd.addClassName("mydomain.test.A");
pumd.setExcludeUnlistedClasses();
pumd.addProperty("javax.persistence.jdbc.url", "jdbc:h2:mem:nucleus");
pumd.addProperty("javax.persistence.jdbc.user", "sa");
pumd.addProperty("javax.persistence.jdbc.password", "");
pumd.addProperty("datanucleus.schema.autoCreateAll", "true");
EntityManagerFactory emf = new JPAEntityManagerFactory(pumd, null);