Создайте JPA EntityManager без сохранения.файл конфигурации xml
есть ли способ, чтобы инициализировать EntityManager
без определенной единицы персистентности? Можно ли предоставить все необходимые свойства для создания диспетчера сущностей? Мне нужно создать EntityManager
из заданных пользователем значений во время выполнения. Обновление persistence.xml
и перекомпиляция не является вариантом.
любая идея о том, как это сделать, более чем приветствуется!
5 ответов
есть ли способ, чтобы инициализировать
EntityManager
без определенной единицы персистентности?
вы должны определить по крайней мере одна единица настойчивости в persistence.xml
дескриптора развертывания.
можете ли вы дать все необходимые свойства для создания
Entitymanager
?
- атрибут имя. Остальные атрибуты и элементы являются необязательными. (Спецификации JPA). Так что это должно быть больше или меньше вашего минимального :
<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
предполагается, что не наша источнику будет обеспечен. В среде 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 (или его эквивалента spring config 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()
is важно так как в противном случае завод не будет построен, а потом getObject()
возвращает null
и вы гонитесь за NullPointerException
s весь день. >:-(
затем он работал со следующим кодом:
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
реализация (например, Hibernate), вы можете использовать PersistenceProvider#createContainerEntityManagerFactory (PersistenceUnitInfo информация, карта карты) метод загрузки EntityManagerFactory
без persistence.xml
.
однако, это раздражает, что вы должны реализовать PersistenceUnitInfo
интерфейс, поэтому вам лучше использовать Spring или Hibernate, которые поддерживают загрузку JPA без persistence.xml
файл:
this.nativeEntityManagerFactory = provider.createContainerEntityManagerFactory(
this.persistenceUnitInfo,
getJpaPropertyMap()
);
здесь PersistenceUnitInfo реализуется с помощью Spring-specific MutablePersistenceUnitInfo класса.
проверить в этой статье для хорошей демонстрации того, как вы можете достичь этой цели с помощью Hibernate.