创建不带persistence.xml配置文件的JPA EntityManager

创建不带persistence.xml配置文件的JPA EntityManager,jpa,runtime,entitymanager,persistence.xml,Jpa,Runtime,Entitymanager,Persistence.xml,是否有方法在未定义持久性单元的情况下初始化EntityManager?能否提供创建实体管理器所需的所有属性?我需要在运行时根据用户指定的值创建EntityManager。更新persistence.xml并重新编译不是一个选项 任何关于如何做到这一点的想法都是非常受欢迎的 是否有方法在未定义持久性单元的情况下初始化EntityManager 您应该在persistence.xml部署描述符中定义至少一个持久化单元 您能否提供创建Entitymanager所需的所有属性 name属性是必需的。其

是否有方法在未定义持久性单元的情况下初始化
EntityManager
?能否提供创建实体管理器所需的所有属性?我需要在运行时根据用户指定的值创建
EntityManager
。更新
persistence.xml
并重新编译不是一个选项

任何关于如何做到这一点的想法都是非常受欢迎的

是否有方法在未定义持久性单元的情况下初始化
EntityManager

您应该在
persistence.xml
部署描述符中定义至少一个持久化单元

您能否提供创建
Entitymanager
所需的所有属性

  • name属性是必需的。其他属性和元素是可选的。(JPA规范)。因此,这或多或少应该是您的最小
    persistence.xml
    文件:

某些性质
在JavaEE环境中,
jta数据源
非jta数据源
元素用于指定持久性提供程序要使用的jta和/或非jta数据源的全局JNDI名称

因此,如果您的目标应用程序服务器支持JTA(JBoss、Websphere、GlassFish),则您的
persistence.xml
如下所示:


jdbc/myDS
如果您的目标应用程序服务器不支持JTA(Tomcat),则您的
persistence.xml
如下所示:


jdbc/myDS
如果您的数据源没有绑定到全局JNDI(例如,在JavaEE容器之外),那么您通常会定义JPA提供者、驱动程序、url、用户和密码属性但是属性名称取决于JPA提供商。因此,对于作为JPA提供者的Hibernate,您的
persistence.xml
文件如下所示:


org.hibernate.ejb.HibernatePersistence
br.com.persistence.SomeClass
事务类型属性

通常,在JavaEE环境中,
RESOURCE\u LOCAL
的事务类型假定将提供非JTA数据源。在JavaEE环境中,如果未指定此元素,则默认为JTA。在Java SE环境中,如果未指定此元素,则可以假定默认值为
RESOURCE\u LOCAL

  • 为了确保Java SE应用程序的可移植性,有必要明确列出持久化单元(JPA规范)中包含的托管持久化类
我需要在运行时从用户指定的值创建
EntityManager

所以用这个:

Map addedorOverrideProperties=newHashMap();
//假设我们使用Hibernate作为JPA提供者
addedorOverrideProperties.put(“hibernate.show_sql”,true);
createEntityManagerFactory(,addedorOverrideProperties);

是的,您可以在@Configuration类(或其等效的spring配置xml)中使用spring,而无需使用任何xml文件:


我能够使用Hibernate和PostgreSQL创建一个
EntityManager
,完全使用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),您可以使用该方法引导
EntityManagerFactory
,而不需要
persistence.xml

但是,您必须实现
PersistenceUnitInfo
接口,这很烦人,因此您最好使用Spring或Hibernate,它们都支持在没有
persistence.xml
文件的情况下引导JPA:

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

其中,由特定于Spring的类实现。

这里有一个没有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();

我使用的DataNucleus 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);

您还可以使用PersistenceContext或Autowired注释获取EntityManager,但请注意它不是线程安全的

@PersistenceContext
私人实体管理者实体管理者;

您好,我尝试了您的解决方案,但遇到了问题,请检查我的问题:但是……问题是如何在没有persistence.xml的情况下创建一个JPA EntityManager。这个答案很好,但它仍然使用persistence.xml,对吗?在JavaEE环境中,创建一个EntityManager工厂,它们是否由EJB/JPA管理?这是一个不错的选择Hibernate。什么对象是
properties
?它是一个简单的java.util.properties对象,使用
MutablePersistenceUnitInfo
作为一些方法不起作用。另外提到的有点过时:
getPersistenceUnitRootUrl
不能返回null,否则Hibernate不会扫描类路径(Hibernate 5.2.8).我有点错误,这篇文章在这方面并没有过时,因为代码正在传递实体列表,并且不使用包扫描。但是对于自动实体扫描,必须实现
getPersistenceUnitRootUrl
getJarFileUrls
。后者在这方面对我帮助很大,因为它帮助我避免了d在一些测试用例中使用arquillian的开销!
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;
        }
    };
}
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);