Domanda

C'è un modo per inizializzare l'EntityManager senza un'unità di persistenza definita? Puoi dare tutte le proprietà richieste per creare un gestore di entità? Ho bisogno di creare il EntityManager dai valori specificati dell'utente in fase di esecuzione. Aggiornamento del persistence.xml e ricompilando non è un'opzione.

Qualche idea su come fare questo è più che benvenuto!

È stato utile?

Soluzione

  

C'è un modo per inizializzare l'EntityManager senza un'unità di persistenza definita?

È necessario definire almeno un'unità di persistenza nel descrittore di distribuzione persistence.xml.

  

Si può dare tutte le proprietà richieste per creare un Entitymanager?

  • è richiesto L'attributo name. Gli altri attributi ed elementi sono opzionali. (Specifica JPA). Quindi questo dovrebbe essere più o meno il file persistence.xml minima:
<persistence>
    <persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
        SOME_PROPERTIES
    </persistence-unit>
</persistence>
  

In ambienti Java EE, gli elementi jta-data-source e non-jta-data-source vengono utilizzati per specificare il nome JNDI globale del JTA e / o fonte di dati non-JTA per essere utilizzato dal provider di persistenza.

Così, se il server di destinazione Applicazione supporta JTA (JBoss, Websphere, GlassFish), il vostro persistence.xml appare come:

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

Se il server di destinazione applicazione non supporta JTA (Tomcat), il vostro persistence.xml appare come:

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

Se l'origine dati non è vincolata ad un JNDI globale (per esempio, al di fuori di un contenitore Java EE), in modo da di solito definire le proprietà del provider JPA, del driver, url, utente e password. Ma nome della proprietà dipende dal provider JPA. Così, per Hibernate come provider JPA, la tua volontà di file persistence.xml appare come:

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

Tipo di transazione attributo

  

In generale, in ambienti Java EE, una transazione di tipo di RESOURCE_LOCAL presuppone che sarà fornito un non-JTA origine dati. In un ambiente Java EE, se questo elemento non è specificato, il valore predefinito è JTA. In un ambiente Java SE, se questo elemento non è specificato, il valore predefinito RESOURCE_LOCAL può essere assunto.

  • Per assicurare la portabilità di un'applicazione Java SE, è necessario elencare esplicitamente le classi di persistenza gestiti che sono inclusi nel gruppo di persistenza (specifica JPA)
  

ho bisogno di creare il EntityManager dai valori specificati dell'utente in fase di esecuzione

Quindi, utilizzare questo:

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

Altri suggerimenti

Sì, è possibile senza l'uso di file XML usando primavera come questo all'interno di una classe @Configuration (o il suo equivalente config primavera 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;
}

Sono stato in grado di creare un EntityManager con Hibernate e PostgreSQL puramente utilizzando il codice Java (con una configurazione di Spring) il seguente:

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

La chiamata al LocalContainerEntityManagerFactoryBean.afterPropertiesSet() è essenziale in quanto altrimenti la fabbrica non viene mai costruito, e poi ritorna getObject() null e ti inseguono dopo NullPointerExceptions tutto il giorno. >: - (

E 'poi lavorato con il seguente codice:

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

Dove il mio soggetto è stato questo:

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

Ecco una soluzione senza molla. Costanti sono presi da 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();

E il famigerato 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;
        }
    };
}

Con pianura APP, a patto che abbiate un'implementazione PersistenceProvider (ad es Hibernate), è possibile utilizzare il PersistenceProvider # createContainerEntityManagerFactory (PersistenceUnitInfo informazioni, mappa mappa) metodo per bootstrap un EntityManagerFactory senza bisogno di un persistence.xml.

Tuttavia, è fastidioso che si deve implementare l'interfaccia PersistenceUnitInfo, così si è meglio utilizzare primavera o Hibernate quale sia il supporto bootstrap JPA senza un file persistence.xml:

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

Dove è implementato il PersistenceUnitInfo dallo specifico-Spring MutablePersistenceUnitInfo classe.

questo articolo per una bella dimostrazione di come si può raggiungere questo obiettivo con Hibernate.

DataNucleus APP che io uso è anche un modo di fare questo nella sua docs . Non c'è bisogno di primavera, o brutto attuazione PersistenceUnitInfo.

È sufficiente fare come segue

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);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top