永続性.xml構成ファイルなしでJPAEntityManagerを作成します


82

EntityManager永続性ユニットを定義せずにを初期化する方法はありますか?エンティティマネージャーを作成するために必要なすべてのプロパティを指定できますか?EntityManager実行時にユーザーが指定した値からを作成する必要があります。の更新persistence.xmlと再コンパイルはオプションではありません。

これを行う方法についてのアイデアは大歓迎です!

回答:


57

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-sourceandnon-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);

:こんにちは、私はあなたが私の質問を確認してください可能性があり、あなたのソリューションを試してみましたが、問題に実行 stackoverflow.com/questions/3935394/...
スタッカー

しかし...問題は、persistence.xmlなしでJPAEntityManagerを作成する方法でした。この答えは良いですが、それでもpersistence.xmlを使用していますよね?
Joshua Davis

JavaEE環境では、EntityManagerFactoryを作成すると、EJB / JPAによって管理されますか?
Anthony Vinay 2018

29

はい、@ Configurationクラス(または同等のspring config xml)内でこのようなspringを使用して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;
}

オブジェクトはproperties何ですか?
脅威2015

これは単純なjava.util.Propertiesオブジェクトです
Frank Orellana 2015

20

これがSpringなしの解決策です。定数は以下から取得され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;
        }
    };
}

3
これは、いくつかのテストケースでarquillianを使用するオーバーヘッドを使用することを回避するのに役立ったので、私を大いに助けました!
cljk 2017年

18

EntityManager純粋にJavaコード(Spring構成)を使用して、HibernateとPostgreSQLで次のように作成することができました。

@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();
}

それ以外の場合、工場は建設されず、その後戻ってきて、一日中sを追いかけているので、への呼び出しLocalContainerEntityManagerFactoryBean.afterPropertiesSet()不可欠です。> :-(getObject()nullNullPointerException

その後、次のコードで動作しました。

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
}

2
Hibernateの優れた代替手段。
javydreamercsw 2014年

8

プレーンJPAでは、PersistenceProvider実装(Hibernateなど)があると仮定すると、PersistenceProvider#createContainerEntityManagerFactory(PersistenceUnitInfo info、Map map)メソッドを使用して、EntityManagerFactoryを必要とせずにブートストラップできpersistence.xmlます。

ただし、PersistenceUnitInfoインターフェースを実装する必要があるのは面倒なので、persistence.xmlファイルなしでJPAのブートストラップをサポートするSpringまたはHibernateを使用することをお勧めします。

this.nativeEntityManagerFactory = provider.createContainerEntityManagerFactory(
    this.persistenceUnitInfo, 
    getJpaPropertyMap()
);

どこPersistenceUnitInfoは春特有で実装されたMutablePersistenceUnitInfoのクラス。


MutablePersistenceUnitInfo一部のメソッドはUnsupportedOperationExceptionをスローするため、使用は機能しません。また、言及された記事は少し古くなっています:getPersistenceUnitRootUrlnullを返すことはできません。そうでない場合、Hibernateはクラスパスをスキャンしません(Hibernate5.2.8)。
ブライス2017

1
私は少し間違っていました。コードがエンティティのリストを渡し、パッケージスキャンを使用しないため、この記事は古くはありません。ただし、自動エンティティスキャンの場合は、getPersistenceUnitRootUrl またはのいずれかを実装する必要がありますgetJarFileUrls。後者はstackoverflow.com/a/42372648/48136に
ブライス

0

私が使用しているDataNucleusJPAには、そのドキュメントでこれを行う方法もあります。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);

0

PersistenceContextまたはAutowiredアノテーションを使用してEntityManagerを取得することもできますが、スレッドセーフではないことに注意してください。

@PersistenceContext
private EntityManager entityManager;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.