Cree EntityManager de JPA sin persistencia.archivo de configuración xml
¿Hay alguna forma de inicializar el EntityManager
sin una unidad de persistencia definida? ¿Puede dar todas las propiedades necesarias para crear un entity manager? Necesito crear el EntityManager
a partir de los valores especificados por el usuario en tiempo de ejecución. Actualizar persistence.xml
y recompilar no es una opción.
Cualquier idea sobre cómo hacer esto es más que bienvenida!
5 answers
¿Hay alguna forma de inicializar el
EntityManager
sin una unidad de persistencia definida?
Debe definir al menos una unidad de persistencia en el descriptor de implementación persistence.xml
.
Puede dar todas las propiedades necesarias para crear un
Entitymanager
?
- Se requiere el atributo name. Los otros atributos y elementos son opcionales. (Especificación JPA). Así que esto debe ser más o menos su mínimo
persistence.xml
archivo:
<persistence>
<persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
SOME_PROPERTIES
</persistence-unit>
</persistence>
En entornos Java EE, los elementos
jta-data-source
ynon-jta-data-source
se utilizan para especificar el nombre JNDI global de la fuente de datos JTA y/o no JTA que utilizará el proveedor de persistencia.
Entonces, si su servidor de aplicaciones de destino admite JTA (JBoss, Websphere, GlassFish), su persistence.xml
se ve como:
<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 su servidor de aplicaciones de destino no es compatible con JTA (Tomcat), su persistence.xml
se ve así:
<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 su fuente de datos no está vinculado a un JNDI global (por ejemplo, fuera de un contenedor de Java EE), por lo que normalmente definiría las propiedades de proveedor, controlador, url, usuario y contraseña de JPA. Pero el nombre de la propiedad depende del proveedor JPA. Por lo tanto, para Hibernate como proveedor de JPA, su archivo persistence.xml
se verá como:
<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>
Atributo de tipo de transacción
En general, en entornos Java EE, un tipo de transacción de
RESOURCE_LOCAL
asume que se proporcionará una fuente de datos no JTA. En un Java EE entorno, si no se especifica este elemento, el valor predeterminado es JTA. En un entorno Java SE, si no se especifica este elemento, se puede asumir un valor predeterminado deRESOURCE_LOCAL
.
- Para asegurar la portabilidad de una aplicación Java SE, es necesario listar explícitamente las clases de persistencia gestionadas que se incluyen en la unidad de persistencia (especificación JPA)
Necesito crear el
EntityManager
a partir de los valores especificados por el usuario en tiempo de ejecución
Así que usa esto:
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);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-26 07:28:34
Sí puede sin usar ningún archivo xml usando spring como este dentro de una clase @Configuration (o su equivalente spring config 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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-10 17:16:42
Pude crear un EntityManager
con Hibernate y PostgreSQL usando puramente código Java (con una configuración de Resorte) lo siguiente:
@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 llamada a LocalContainerEntityManagerFactoryBean.afterPropertiesSet()
es esencial ya que de lo contrario la fábrica nunca se construye, y luego getObject()
devuelve null
y estás persiguiendo NullPointerException
s todo el día. >:-(
Luego trabajó con el siguiente código:
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();
Donde mi entidad era esta:
@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
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-16 21:11:10
Aquí hay una solución sin resorte.
Las constantes se toman 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();
Y el infame 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;
}
};
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-21 16:35:02
Con JPA simple, suponiendo que tenga una implementación PersistenceProvider
(por ejemplo, Hibernate), puede usar el método PersistenceProvider#createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) para arrancar un EntityManagerFactory
sin necesidad de un persistence.xml
.
Sin embargo, es molesto que tenga que implementar la interfaz PersistenceUnitInfo
, por lo que es mejor usar Spring o Hibernate que ambos admiten bootstrapping JPA sin un archivo persistence.xml
:
this.nativeEntityManagerFactory = provider.createContainerEntityManagerFactory(
this.persistenceUnitInfo,
getJpaPropertyMap()
);
Donde el PersistenceUnitInfo está implementado por la clase MutablePersistenceUnitInfo específica de Spring.
Echa un vistazo a este artículo para una buena demostración de cómo puedes lograr este objetivo con Hibernate.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-05 13:26:47