Question

Est-il possible d'initialiser le EntityManager sans unité de persistance définie? Pouvez-vous donner toutes les propriétés requises pour créer un gestionnaire d'entités? Je dois créer le EntityManager à partir des valeurs spécifiées par l'utilisateur lors de l'exécution. Mise à jour du persistence.xml et recompilation n'est pas une option.

Toute idée sur la façon de le faire est plus que bienvenue!

Était-ce utile?

La solution

  

Est-il possible d'initialiser le EntityManager sans unité de persistance définie?

Vous devez définir au moins une unité de persistance dans le descripteur de déploiement persistence.xml.

  

Pouvez-vous donner toutes les propriétés requises pour créer un Entitymanager?

  • L'attribut name est nécessaire. Les autres attributs et éléments sont facultatifs. (Spécification APP). Donc, cela devrait être plus ou moins votre fichier persistence.xml minimal:
<persistence>
    <persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
        SOME_PROPERTIES
    </persistence-unit>
</persistence>
  

Dans les environnements Java EE, les jta-data-source et les éléments non-jta-data-source sont utilisés pour spécifier le nom JNDI global de la JTA et / ou non-JTA source de données pour être utilisé par le fournisseur de persistance.

Donc, si votre cible Application Server prend en charge JTA (JBoss, Websphere, GlassFish), votre persistence.xml ressemble à:

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

Si votre cible Application Server ne, votre persistence.xml ressemble supporte pas JTA (Tomcat):

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

Si votre source de données ne sont pas liés à un JNDI global (par exemple, en dehors d'un conteneur Java EE), de sorte que vous définirait généralement fournisseur JPA, pilote, url, utilisateur et mot de passe propriétés. Mais nom de la propriété dépend du fournisseur JPA. Ainsi, pour Hibernate en tant que fournisseur JPA, votre fichier persistence.xml volonté ressemble à:

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

Type de transaction Attribut

  

En général, dans les environnements Java EE, une transaction de type de RESOURCE_LOCAL suppose qu'une source de données non-JTA sera fourni. Dans un environnement Java EE, si cet élément n'est pas spécifié, la valeur par défaut est JTA. Dans un environnement Java SE, si cet élément n'est pas spécifié, un défaut de RESOURCE_LOCAL peut supposer.

  • Pour assurer la portabilité d'une application Java SE, il est nécessaire d'énumérer explicitement les classes de persistance gérées qui sont inclus dans l'unité de persistance (JPA)
  

Je dois créer le EntityManager à partir des valeurs spécifiées par l'utilisateur lors de l'exécution

Il faut donc utiliser ceci:

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);

Autres conseils

Oui, vous pouvez sans utiliser un fichier XML à l'aide du printemps comme celui-ci dans une classe @Configuration (ou son xml de configuration ressort équivalent):

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

Je suis en mesure de créer un EntityManager avec Hibernate et PostgreSQL uniquement à l'aide du code Java (avec une configuration de ressort) qui suit:

@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();
}

L'appel à LocalContainerEntityManagerFactoryBean.afterPropertiesSet() est essentiel car sinon l'usine se construit jamais, puis getObject() retours null et vous pourchassent après NullPointerExceptions toute la journée. >: - (

Il a ensuite travaillé avec le code suivant:

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();

Si mon entité était la suivante:

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

Voici une solution sans ressort. Constantes sont prises à partir 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();

Et le PersistenceUnitInfo infâme

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 simple, en supposant que vous avez une implémentation PersistenceProvider (par exemple Hibernate), vous pouvez utiliser le PersistenceProvider # createContainerEntityManagerFactory (PersistenceUnitInfo informations, carte carte) méthode pour bootstrap une EntityManagerFactory sans avoir besoin d'un persistence.xml.

Cependant, il est ennuyeux que vous devez implémenter l'interface PersistenceUnitInfo, vous feriez mieux d'utiliser Spring ou Hibernate qui à la fois le soutien bootstrapping JPA sans fichier persistence.xml:

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

Si le PersistenceUnitInfo est mis en œuvre par le spécifique au printemps classe de MutablePersistenceUnitInfo.

Consultez cet article pour une belle démonstration de la façon dont vous pouvez atteindre cet objectif avec Hibernate.

DataNucleus JPA que j'utiliser a aussi une façon de le faire dans sa docs . Pas besoin pour le printemps ou la mise en œuvre de laide PersistenceUnitInfo.

Il suffit de faire comme suit

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);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top