创build没有persistence.xmlconfiguration文件的JPA EntityManager
有没有一种方法来初始化EntityManager
没有定义持久性单元? 你可以给所有必要的属性来创build一个实体经理? 我需要在运行时从用户指定的值创buildEntityManager
。 更新persistence.xml
并重新编译不是一个选项。
任何想法如何做到这一点是比欢迎!
有没有一种方法来初始化
EntityManager
没有定义持久性单元?
您应该在persistence.xml
部署描述符中至less定义一个持久性单元。
你可以给所有必需的属性来创build一个
Entitymanager
?
- name属性是必需的。 其他属性和元素是可选的。 (JPA规范)。 所以这应该或多或less是你最小的
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
元素用于指定持久化提供程序要使用的JTA和/或非JTA数据源的全局JNDI名称 。
因此,如果您的目标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提供程序,驱动程序,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>
交易types属性
通常,在Java EE环境中,事务types的
RESOURCE_LOCAL
假定将提供非JTA数据源。 在Java EE环境中,如果未指定此元素,则默认为JTA。 在Java SE环境中,如果未指定此元素,则可以假定为缺省的RESOURCE_LOCAL
。
- 为了确保Java SE应用程序的可移植性,有必要明确列出持久化单元(JPA规范)中包含的托pipe持久化类,
我需要在运行时从用户指定的值创build
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);
是的,你可以在@Configuration类(或其等价的spring config xml)中使用像这样使用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; }
我能够用Hibernate和PostgreSQL创build一个EntityManager
,纯粹使用Java代码(使用Springconfiguration):
@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()
的调用是必不可less的 ,否则工厂永远不会被构build,然后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的解决scheme。 常量取自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 info,Map map)来引导一个EntityManagerFactory
而不需要一个persistence.xml
。
然而,你不得不实现PersistenceUnitInfo
接口,所以你最好使用Spring或者Hibernate,它们都支持在没有persistence.xml
文件的情况下引导JPA:
this.nativeEntityManagerFactory = provider.createContainerEntityManagerFactory( this.persistenceUnitInfo, getJpaPropertyMap() );
PersistenceUnitInfo是由特定于Spring的MutablePersistenceUnitInfo类实现的。
看看这篇文章 ,了解如何通过Hibernate实现这个目标。