有没有办法初始化 EntityManager 没有定义持久性单元?您能否提供创建实体管理器所需的所有属性?我需要创建 EntityManager 来自用户在运行时指定的值。更新中 persistence.xml 并且重新编译不是一个选择。

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

有帮助吗?

解决方案

有没有一种方法来初始化 EntityManager 没有一个持久性单元定义?

你应该定义 至少 一个持久性单元在 persistence.xml 部署的描述符。

你可以给所有要求的性质以创建一个 Entitymanager?

  • 该名称属性是必需的。其他属性和元素都是可选的。(访问用户说明书)。所以这应该是或多或少你最小 persistence.xml 文件:
<persistence>
    <persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
        SOME_PROPERTIES
    </persistence-unit>
</persistence>

在Java EE环境, jta-data-sourcenon-jta-data-source 元素是用于指定 全球参JTA的和/或非JTA数据来源 可以使用由持久的供应商。

所以如果你的目标应用程序服务器的支持JTA(Boss,Websphere、玻),您的 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容器),因此通常定义访问用户提供者、驱动器、网址,用户名和密码的性质。 酒店名字取决于访问用户的提供者。因此,对于休眠作为访问用户提供者、你的 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应用程序, 有必要明确地列表 在管理持久性的课程,都包含在持久性单元(访问用户的规范)

我需要创造 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类中任何XML文件(或其等价的弹簧配置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纯粹使用Java代码(具有Spring配置)以下内容的EntityManager

@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
}

下面是不使用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;
        }
    };
}

使用普通 JPA,假设您有 PersistenceProvider 实施(例如休眠),您可以使用 PersistenceProvider#createContainerEntityManagerFactory(PersistenceUnitInfo信息,Map地图) 引导方法 EntityManagerFactory 无需 persistence.xml.

然而,令人烦恼的是你必须实施 PersistenceUnitInfo 接口,所以你最好使用 Spring 或 Hibernate,它们都支持引导 JPA,无需 persistence.xml 文件:

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

哪里的 持久化单元信息 由Spring特定的实现 可变持久性单元信息 班级。

查看 本文 很好地演示了如何使用 Hibernate 实现此目标。

DataNucleus将JPA,我使用还具有这样的在其文档。无需春天,还是丑陋的实施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);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top