2010-01-01 2 views
63

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

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

ответ

53

Есть ли способ инициализировать 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, который будет использоваться поставщиком сохранения.

Так что, если ваша цель Application Server поддерживает 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> 

Если ваша цель Application Server не поддерживает 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, водитель, у rl, свойства пользователя и пароля. Но имя зависит от поставщика 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)

I необходимо создать 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); 
+0

Привет Я попробовал ваше решение, но столкнуться с проблемами, не могли бы вы проверить мой вопрос: http://stackoverflow.com/ Вопросы/3935394/how-to-externalize-properties-from-jpas-persistence-xml – stacker

+0

@stacker Я проверяю –

21

Да, вы можете без использования какого-либо файл XML с помощью пружины, как это внутри класса @Configuration (или его эквивалента пружинных конфигураций 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; 
} 
+0

Какой объект является 'свойствами'? – ThreaT

+0

это простой объект java.util.Properties –

12

Я был в состоянии создать 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() является essential, так как в противном случае завод никогда не строится, а затем 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 
} 
+1

Хорошая альтернатива для спящего режима. – javydreamercsw

3

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

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

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

Если PersistenceUnitInfo осуществляется весеннем конкретных MutablePersistenceUnitInfo класса.

Отъезд this article для приятной демонстрации того, как вы можете достичь этой цели с помощью Hibernate.

+0

Использование 'MutablePersistenceUnitInfo' не работает как некоторые методы [throw UnsupportedOperationException] (https://github.com/spring-projects/spring-framework/blob/4.3.x/spring-orm/src/main/java/org/ springframework/ОРМ/JPA/persistenceunit/MutablePersistenceUnitInfo.java # L272-L274). Кроме того, ссылка [article] (https://vladmihalcea.com/2015/11/26/how-to-bootstrap-hibernate-without-the-persistence-xml-file/) немного устарела: 'getPersistenceUnitRootUrl' не может вернуться null в противном случае Hibernate не сканирует путь к классам (Hibernate 5.2.8). – Brice

+0

Я был немного не прав, статья не устарела в этом отношении, поскольку код передает список сущностей и не использует сканирование пакетов. Однако для автоматического сканирования объектов необходимо реализовать либо 'getPersistenceUnitRootUrl', либо' getJarFileUrls'. Позднее посеяно в http://stackoverflow.com/a/42372648/48136 – Brice

10

Вот решение без весны. Константы взяты из 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

Смежные вопросы