Crear JPA EntityManager sin archivo de configuración persistence.xml

¿Hay alguna manera de inicializar EntityManager sin una unidad de persistencia definida? ¿Puedes dar todas las propiedades requeridas para crear un administrador de entidades? Necesito crear EntityManager partir de los valores especificados por el usuario en el tiempo de ejecución. La actualización de persistence.xml y la recomstackción no es una opción.

¡Cualquier idea sobre cómo hacer esto es más que bienvenida!

¿Hay alguna manera de inicializar EntityManager sin una unidad de persistencia definida?

Debe definir al menos una unidad de persistencia en el descriptor de despliegue persistence.xml .

¿Puedes dar todas las propiedades requeridas para crear un Entitymanager ?

  • El atributo de nombre es obligatorio. Los otros atributos y elementos son opcionales. (Especificación JPA). Así que este debería ser más o menos tu mínimo archivo persistence.xml :
   SOME_PROPERTIES   

En los entornos Java EE, los elementos jta-data-source y non-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 objective admite JTA (JBoss, Websphere, GlassFish), su persistence.xml ve así:

    jdbc/myDS   

Si su servidor de aplicaciones objective no es compatible con JTA (Tomcat), su persistence.xml ve así:

    jdbc/myDS   

Si su fuente de datos no está vinculada a un JNDI global (por ejemplo, fuera de un contenedor Java EE), entonces normalmente definiría las propiedades del proveedor, el controlador, la url, el usuario y la contraseña de JPA. Pero el nombre de la propiedad depende del proveedor de JPA. Entonces, para Hibernate como proveedor de JPA, su archivo persistence.xml tendrá el siguiente aspecto:

   org.hibernate.ejb.HibernatePersistence br.com.persistence.SomeClass         

Tipo de transacción Atributo

En general, en entornos Java EE, un tipo de transacción de RESOURCE_LOCAL supone que se proporcionará un origen de datos no JTA. En un entorno Java EE, si este elemento no está especificado, el valor predeterminado es JTA. En un entorno Java SE, si no se especifica este elemento, se puede suponer un valor predeterminado de RESOURCE_LOCAL .

  • Para asegurar la portabilidad de una aplicación Java SE, es necesario enumerar explícitamente las clases de persistencia administradas que se incluyen en la unidad de persistencia (especificación JPA)

Necesito crear EntityManager partir de los valores especificados por el usuario en el tiempo de ejecución

Entonces usa esto:

 Map addedOrOverridenProperties = new HashMap(); // Let's suppose we are using Hibernate as JPA provider addedOrOverridenProperties.put("hibernate.show_sql", true); Persistence.createEntityManagerFactory(, addedOrOverridenProperties); 

Sí, puedes hacerlo sin usar ningún archivo xml usando un resorte como este dentro de una clase @Configuration (o su configuración de spring equivalente 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; } 

Pude crear un EntityManager con Hibernate y PostgreSQL usando puramente código Java (con una configuración de Spring) de la siguiente manera:

 @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 getObject() , y luego getObject() devuelve null y se está persiguiendo a NullPointerException s durante 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 esto:

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

Aquí hay una solución sin Spring. Las constantes se toman de org.hibernate.cfg.AvailableSettings :

 entityManagerFactory = new HibernatePersistenceProvider().createContainerEntityManagerFactory( archiverPersistenceUnitInfo(), ImmutableMap.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 la 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 getMappingFileNames() { return Collections.emptyList(); } @Override public List 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 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 JPA simple, suponiendo que tiene una implementación PersistenceProvider (por ejemplo, Hibernate), puede usar el método PersistenceProvider # createContainerEntityManagerFactory (PersistenceUnitInfo, Map map) para EntityManagerFactory una EntityManagerFactory sin necesidad de un persistence.xml .

Sin embargo, es molesto que tenga que implementar la interfaz PersistenceUnitInfo , por lo que es mejor utilizar Spring o Hibernate, que son compatibles con bootstrapping JPA sin un archivo persistence.xml :

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

Donde PersistenceUnitInfo se implementa mediante la clase MutablePersistenceUnitInfo específica de Spring .

Echa un vistazo a este artículo para ver una buena demostración de cómo puedes lograr este objective con Hibernate.

    Intereting Posts