Créer JPA EntityManager sans persistance.fichier de configuration xml

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

toute idée sur la façon de faire ceci est plus que bienvenu!

69
demandé sur Martijn Pieters 2010-01-02 00:19:28

5 réponses

Est-il un moyen d'initialiser le EntityManager sans une unité de persistance?

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 nécessaires pour créer un Entitymanager ?

  • l'attribut name est requis. Les autres les attributs et les éléments sont optionnels. (Spécification JPA). Donc ceci devrait être plus ou moins votre fichier minimal persistence.xml :
<persistence>
    <persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
        SOME_PROPERTIES
    </persistence-unit>
</persistence>

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

donc si votre serveur d'Application cible 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 serveur d'Application cible ne supporte pas JTA (Tomcat), votre persistence.xml ressemble à:

<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 n'est pas liée à un JNDI global (par exemple, en dehors d'un conteneur Java EE), vous définiriez généralement JPA provider, driver, url, user et password properties. mais le nom de la propriété dépend de fournisseur JPA. Donc, pour L'hibernation en tant que fournisseur de JPA, votre fichier persistence.xml ressemblera à:

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

Attribut Du Type De Transaction

en général, dans les environnements Java EE, un type de transaction RESOURCE_LOCAL suppose qu'une source de données non JTA sera fournie. 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é, une valeur par défaut de RESOURCE_LOCAL peut être supposé.

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

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

alors utilisez 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);
55
répondu Arthur Ronald 2016-08-26 07:28:34

Oui vous pouvez sans utiliser n'importe quel fichier xml en utilisant le ressort comme ceci dans une classe @Configuration (ou son équivalent XML de config de ressort):

@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;
}
23
répondu Frank Orellana 2014-12-10 17:16:42

j'ai pu créer un EntityManager avec hibernation et PostgreSQL en utilisant uniquement le code Java (avec une configuration à ressort) comme 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 autrement l'usine ne se construit jamais, puis getObject() retourne null et vous chassez après NullPointerException s 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();

où mon entité était:

@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
}
15
répondu ArtB 2015-05-16 21:11:10

Voici une solution sans ressort. Les constantes sont tirées de 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 l'infâme 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;
        }
    };
}
13
répondu Brice 2017-02-21 16:35:02

avec simple JPA, en supposant que vous avez une implémentation PersistenceProvider (par ex. Hibernate), vous pouvez utiliser la méthode PersistenceProvider#createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) pour bootstrap un EntityManagerFactory sans avoir besoin d'un persistence.xml .

cependant, il est ennuyeux que vous ayez à mettre en œuvre l'interface PersistenceUnitInfo , donc vous êtes mieux d'utiliser le ressort ou L'hibernation qui les deux soutiennent bootstrapping JPA sans un persistence.xml fichier:

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

où le Persistenence Unitinfo est mis en œuvre par le ressort spécifique Mutablepersistence Unitinfo classe.

Check out cet article pour une belle démonstration de la façon dont vous pouvez atteindre cet objectif avec mise en veille prolongée.

4
répondu Vlad Mihalcea 2018-01-05 13:26:47