Есть ли способ инициализировать EntityManager
без определения единицы сохранения?
В дескрипторе развертывания следует определить как минимум одну единицу сохранения состояния persistence.xml
.
Можете ли вы предоставить все необходимые свойства для создания Entitymanager
?
- Атрибут имени является обязательным. Остальные атрибуты и элементы необязательны. (Спецификация 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 (JBoss, Websphere, GlassFish), ваш persistence.xml
вид выглядит так:
<persistence>
<persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_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]">
<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();
addedOrOverridenProperties.put("hibernate.show_sql", true);
Persistence.createEntityManagerFactory(<PERSISTENCE_UNIT_NAME_GOES_HERE>, addedOrOverridenProperties);
Да, вы можете без использования какого-либо xml-файла, используя spring, подобный этому, внутри класса @Configuration (или его эквивалентную конфигурацию 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
?Вот решение без 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; } }; }
источник
Я смог создать с
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
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 }
источник
С обычным JPA, предполагая, что у вас есть
PersistenceProvider
реализация (например, Hibernate), вы можете использовать метод PersistenceProvider # createContainerEntityManagerFactory (информация PersistenceUnitInfo, карта карты) для начальной загрузкиEntityManagerFactory
без необходимости использованияpersistence.xml
.Однако раздражает, что вам нужно реализовать
PersistenceUnitInfo
интерфейс, поэтому вам лучше использовать Spring или Hibernate, которые поддерживают загрузку JPA безpersistence.xml
файла:this.nativeEntityManagerFactory = provider.createContainerEntityManagerFactory( this.persistenceUnitInfo, getJpaPropertyMap() );
Где PersistenceUnitInfo реализуется классом MutablePersistenceUnitInfo, специфичным для Spring .
источник
MutablePersistenceUnitInfo
не работает, поскольку некоторые методы вызывают исключение UnsupportedOperationException . Также упомянутая статья немного устарела:getPersistenceUnitRootUrl
не может вернуть null, иначе Hibernate не сканирует путь к классам (Hibernate 5.2.8).getPersistenceUnitRootUrl
илиgetJarFileUrls
. Последний посеян в stackoverflow.com/a/42372648/48136DataNucleus 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);
источник
Вы также можете получить EntityManager с помощью аннотации PersistenceContext или Autowired, но имейте в виду, что это не будет потокобезопасным.
@PersistenceContext private EntityManager entityManager;
источник