1. Introducción
Se pueden crear persistence units programaticamente en estas condiciones:
- Utilizando Spring (ver stack overflow)
- Utilizando Hibernate (ver el mismo link en stack overflow)
- Implementando la interface PersistenceProvider (ver el mismo link en stack overflow y JPA API
Cogiendo un poco de cada uno he creado las siguientes clases
- MyConnectionProps (propiedades de la conexión)
- PersistenceUnitInfoEdu (clase intermedia que sustituye al persistence.xml)
- JPANoPersistencexmlUtils
Recordar que para que funcione hay que crear la BD en H2!
Veamos la primera
2. MyConnectionProps
Como se puede ver, hemos definido propiedades para 2 conexiones, la primera a una BD Postgres, y la segunda para una BD H2.
package openadmin.utils.nopersistencexml;import java.util.Properties; public class MyConnectionProps { /** * Connection for a Postgres DB * @return */ public static Properties getPropsPostgres() { Properties props=new Properties(); props.put("hibernate.dialect" , "org.hibernate.dialect.PostgreSQLDialect"); props.put("hibernate.hbm2ddl.auto" , "update"); props.put("hibernate.show_sql" , "true"); props.put("hibernate.cache.provider_class" , "org.hibernate.cache.HashtableCacheProvider"); props.put("hibernate.connection.url" , "jdbc:postgresql://192.168.11.11:5432/myDB"); props.put("hibernate.connection.driver_class" , "org.postgresql.Driver"); props.put("hibernate.connection.username" , "my_user"); props.put("hibernate.connection.password" , "my_password"); return props; } /** * /** * Connection for a H2 DB * @return */ public static Properties getPropsH2() { Properties props=new Properties(); props.put("hibernate.dialect" , "org.hibernate.dialect.H2Dialect"); props.put("hibernate.hbm2ddl.auto" , "update");
props.put("hibernate.show_sql" , "true"); props.put("hibernate.cache.provider_class" , "org.hibernate.cache.HashtableCacheProvider"); props.put("hibernate.connection.url" , "jdbc:h2:tcp://localhost/~/test"); props.put("hibernate.connection.driver_class" , "org.h2.Driver"); props.put("hibernate.connection.username" , "my_user"); props.put("hibernate.connection.password" , "my_password"); return props; } }
2. PersistenceUnitInfoEdu
Esta clase se quedará ahí y solo la referenciaremos. Es una clase que guarda las propiedades que se tendrían en el persistence.xml
package openadmin.utils.nopersistencexml; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.persistence.SharedCacheMode; import javax.persistence.ValidationMode; import javax.persistence.spi.ClassTransformer; import javax.persistence.spi.PersistenceUnitInfo; import javax.persistence.spi.PersistenceUnitTransactionType; import javax.sql.DataSource; import lombok.Getter; import lombok.Setter; public class PersistenceUnitInfoEdu implements PersistenceUnitInfo { public static String JPA_VERSION = "2.2"; @Getter @Setter private String persistenceUnitName; //OK @Getter @Setter private PersistenceUnitTransactionType transactionType = PersistenceUnitTransactionType.RESOURCE_LOCAL; //OK @Getter @Setter private String persistenceProviderClassName="org.hibernate.jpa.HibernatePersistenceProvider"; //OK @Getter @Setter private DataSource jtaDataSource=null; //OK a falta de JNI @Getter @Setter private DataSource nonJtaDataSource=null; //OK a falta del no JNI @Getter @Setter private List<String> mappingFileNames = new ArrayList<>(); //OK @Getter @Setter private List<URL> jarFileUrls=null; //OK @Getter @Setter private URL persistenceUnitRootUrl=null; //OK @Getter @Setter private List<String> managedClassNames = new ArrayList<>(); //OK @Getter @Setter private boolean excludeUnlistedClasses=false; //OK @Getter @Setter private SharedCacheMode sharedCacheMode=null; //OK @Getter @Setter private ValidationMode validationMode=ValidationMode.AUTO; //OK @Getter @Setter private Properties properties=null; //OK @Getter @Setter private String persistenceXMLSchemaVersion=JPA_VERSION; //OK @Getter @Setter private ClassLoader classLoader=null; //OK @Getter @Setter private List<ClassTransformer> transformers = new ArrayList<>(); //OK addTransformes @Getter @Setter private ClassTransformer transformer=null; @Getter @Setter private ClassLoader newTempClassLoader=null; //OK public PersistenceUnitInfoEdu(String persistenceUnitName, List<String> managedClassNames, boolean excludeUnlistedClasses, Properties properties) { this.persistenceUnitName = persistenceUnitName; this.managedClassNames = managedClassNames; this.excludeUnlistedClasses=excludeUnlistedClasses; this.properties = properties; } @Override public boolean excludeUnlistedClasses() { return excludeUnlistedClasses; } @Override public void addTransformer(ClassTransformer transformer) { // TODO Auto-generated method stub } }
3. JPANoPersistencexmlUtils
Clase con métodos estáticos para poder crear finalmente el EntityManagerFactory, y que en el "main" hemos hecho una prueba para abrir una BD H2 y leer los registros de la tabla "TEST". Si no estuviera creada la tabla, como hemos incluido la opción de actualizar la BD, crearía esta tabla.
package openadmin.utils.nopersistencexml; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Query; import javax.persistence.spi.PersistenceUnitInfo; import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl; import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor; import openadmin.utils.HibernateUtils2; import openadmin.utils.Test; public class JPANoPersistenceUtils { private static PersistenceUnitInfoEdu getPsInitInfo(String persistenceUnitName, List<String> managedClassNames, boolean excludeUnlistedClasses, Properties properties) { return new PersistenceUnitInfoEdu(persistenceUnitName, managedClassNames, excludeUnlistedClasses, properties); } public static EntityManagerFactory getEntityManagerFactory(String persistenceUnitName, List<String> managedClassNames, boolean excludeUnlistedClasses, Properties properties) { PersistenceUnitInfo persistenceUnitInfo = getPsInitInfo(persistenceUnitName,managedClassNames,excludeUnlistedClasses,properties); Map<String, Object> configuration = new HashMap<>(); return new EntityManagerFactoryBuilderImpl( new PersistenceUnitInfoDescriptor(persistenceUnitInfo), configuration) .build(); } public static void main(String[] args) { List<String>classes=new ArrayList<String>(); classes.add("openadmin.utils.nopersistencexml.Test"); EntityManagerFactory emf=getEntityManagerFactory("my-h2",classes,true,MyConnectionPrtops.getPropsH2()); EntityManager em=emf.createEntityManager(); //Query q=em.createNativeQuery("SELECT * FROM TEST"); Query q=em.createQuery("SELECT t FROM Test t WHERE t.id<1000"); List<Test> ltest=q.getResultList(); for (Test t:ltest) System.out.println(t.getId()+"-"+ t.getName()); em.close(); emf.close(); } }
Las líneas de amarillo són las que aportan la información al respecto
Veamos ahora elementos complementarios:
4. La entidad Test
Esta clase es la que se ha hecho la persistencia
package openadmin.utils.nopersistencexml;import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import lombok.Getter; import lombok.Setter; @Entity @Table(name = "TEST") public class Test { @Id @Column(name="ID") @Getter @Setter private Integer id; @Getter @Setter @Column(name="NAME") private String name; //Getters and setters omitted for brevity }
Veamos ahora el build.gradle
5. build.gradle
Tenga cuidado de incluir javax.validation solo para versiones de Hibernate >=5.5, en las versiones anteriores debe eliminar esta entrada.
/* * This file was generated by the Gradle 'init' task. * * This generated file contains a sample Java library project to get you started. * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle * User Manual available at https://docs.gradle.org/7.0.2/userguide/building_java_projects.html */ plugins { // Apply the java-library plugin for API and implementation separation. id 'java-library' } repositories { // Use JCenter for resolving dependencies. jcenter() mavenCentral() } // My customization //project.jar.destinationDirectory = file("$rootDir/mytarget") project.jar.destinationDirectory = file("$rootDir/../mytargets") project.archivesBaseName = 'c-dao' project.version = '1.0' dependencies { // Use JUnit test framework. testImplementation 'junit:junit:4.13' /*********************************************************************** *********************** LOMBOK DEFINITION ******************************/ compileOnly 'org.projectlombok:lombok:1.18.20' annotationProcessor 'org.projectlombok:lombok:1.18.20' testCompileOnly 'org.projectlombok:lombok:1.18.20' testAnnotationProcessor 'org.projectlombok:lombok:1.18.20' /************************************************************************/ /* Apache.commons */ implementation "org.apache.commons:commons-exec:1.3" /* Apache general */ implementation "commons-io:commons-io:2.11.0" implementation "org.apache.commons:commons-lang3:3.12.0" /* Jakarta --> Need plugin "war" */ //providedCompile "jakarta.annotation:jakarta.annotation-api:2.0.0" compileOnly "jakarta.annotation:jakarta.annotation-api:2.0.0"
/* javax.validation--> Use only for hibernate >=5.5 Versions.*//* In lower hibernate versions , remove this entry!!!!!! */
implementation "javax.validation:validation-api:2.0.1.Final"
/* HIbernate */ implementation "org.hibernate:hibernate-core:5.4.31.Final" implementation "org.hibernate:hibernate-envers:5.4.31.Final" //implementation "org.hibernate:hibernate-testing:5.4.31.Final" implementation "org.hibernate:hibernate-validator:7.0.1.Final" // https://mvnrepository.com/artifact/org.hibernate/hibernate-entitymanager implementation 'org.hibernate:hibernate-entitymanager:5.4.31.Final' /*DB Drivers */ implementation "org.postgresql:postgresql:42.2.20" implementation "net.sourceforge.jtds:jtds:1.3.1" implementation 'com.h2database:h2:1.4.200' } jar { from sourceSets.main.allSource //Include java sources }