Создайте JPA EntityManager без сохранения.XML-файл конфигурации
есть ли способ, чтобы инициализировать EntityManager без определенной единицы персистентности? Можете ли вы дать все необходимые свойства для создания entity manager? Мне нужно создать EntityManager из заданных пользователем значений во время выполнения. Обновление persistence.xml и перекомпиляция не является опцией.
любая идея о том, как это сделать, более чем приветствуется!
5 ответов:
есть ли способ, чтобы инициализировать
EntityManagerбез определенной единицы персистентности?вы должны определить по крайней мере один блок персистентности в
persistence.xmlдескриптора развертывания.можете ли вы дать все необходимые свойства для создания
Entitymanager?
- атрибут name является обязательным. Остальные атрибуты и элементы являются необязательными. (Спецификации JPA). Так что это должно быть больше или меньше ваш минимальный
persistence.xmlfile:<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. Итак, для гибернации в качестве поставщика 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 (или его эквивалента 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()и важно так как в противном случае завод не будет построен, а потомgetObject()возвращаетnullа ты гоняешься заNullPointerExceptions в течение всего дня. >:- (затем он работал со следующим кодом:
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();и печально известный
PersistenceUnitInfoprivate 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 info, Map map) метод начальной загрузкиEntityManagerFactoryбезpersistence.xml.однако, это раздражает, что вы должны реализовать
PersistenceUnitInfoинтерфейс, так что вам лучше использовать Spring или Hibernate, которые оба поддерживают загрузку JPA безpersistence.xmlфайл:this.nativeEntityManagerFactory = provider.createContainerEntityManagerFactory( this.persistenceUnitInfo, getJpaPropertyMap() );здесь PersistenceUnitInfo реализуется пружинно-специфическим MutablePersistenceUnitInfo класса.
проверить в этой статье для хорошей демонстрации того, как вы можете достичь этой цели с помощью Hibernate.
Comments