Создайте JPA EntityManager без файла конфигурации persistence.xml.

StackOverflow https://stackoverflow.com/questions/1989672

Вопрос

Есть ли способ инициализировать EntityManager без определения единицы персистентности?Можете ли вы указать все необходимые свойства для создания менеджера сущностей?мне нужно создать EntityManager из указанных пользователем значений во время выполнения.Обновление persistence.xml и перекомпиляция не вариант.

Любая идея о том, как это сделать, более чем приветствуется!

Это было полезно?

Решение

Есть ли способ инициализировать EntityManager без определения единицы персистентности?

Вы должны определить по меньшей мере одна единица персистентности в 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 элементы используются для указания глобальное имя JNDI источника данных JTA и/или источника данных, отличного от JTA. будет использоваться поставщиком постоянства.

Итак, если ваш целевой сервер приложений поддерживает 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.Итак, для Hibernate как провайдера JPA ваш 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);

Другие советы

Да, вы можете, не используя какой-либо XML-файл, используя Spring, подобный этому, внутри класса @Configuration (или его эквивалентного XML-файла конфигурации Spring):

@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
}

Вот решение без 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;
        }
    };
}

С простым JPA, предполагая, что у вас есть PersistenceProvider реализация (например,Спящий режим), вы можете использовать PersistenceProvider#createContainerEntityManagerFactory (информация PersistenceUnitInfo, карта карты) метод загрузки EntityManagerFactory без необходимости persistence.xml.

Однако раздражает то, что вам приходится реализовывать PersistenceUnitInfo интерфейс, поэтому вам лучше использовать Spring или Hibernate, которые поддерживают загрузку JPA без persistence.xml файл:

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

Где PersistenceUnitInfo реализуется специфичным для 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);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top