manager - jpa java examples
¿Carga programáticamente las clases de Entity con JPA 2.0? (3)
Con Hibernate puede cargar sus clases de Entity
como:
sessionFactory = new AnnotationConfiguration()
.addPackage("test.animals")
.addAnnotatedClass(Flight.class)
.addAnnotatedClass(Sky.class)
.addAnnotatedClass(Person.class)
.addAnnotatedClass(Dog.class);
¿Hay alguna manera de hacer lo mismo, cargar programáticamente las clases de Entity, de forma compatible con JPA 2.0?
La razón de esta pregunta es porque me gustaría cargar dinámicamente mis clases de Entity
, por lo tanto no necesariamente de forma programática.
¿Hay alguna manera de hacer lo mismo, cargar programáticamente las clases de Entity, de forma compatible con JPA 2.0?
No, esto no es compatible con JPA, por lo que tendrás que hacer esto de forma específica para el proveedor. James Sutherland describió el proceso para EclipseLink en este hilo de la siguiente manera:
Puede acceder a EclipseLink
ServerSession
desdeEntityManagerFactoryImpl
(getServerSession()
) y usar suaddDescriptor(ClassDescriptor)
''addDescriptor(ClassDescriptor)
oaddDescriptors()
para agregar EclipseLinkClassDescriptor
. Tendrá que crear losClassDescriptor
metadatos deClassDescriptor
directamente usted mismo (o usar el Mapping Workbench para crearlos), ya que cargar las anotaciones de JPA u orm.xml sería más difícil.
También eche un vistazo a este hilo más reciente para obtener más ejemplos de código (la API parece un poco prolija).
Referencias
Con la ayuda de Spring, hice esto de forma compatible con JPA.
Mi "persistence.xml" parece vacío, sin entidades enumeradas dentro del elemento <persistence-unit>
.
Luego escribí una clase que implementó PersistenceUnitPostProcessor de la siguiente manera:
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import org.reflections.Reflections;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo;
import org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor;
public class ReflectionsPersistenceUnitPostProcessor implements PersistenceUnitPostProcessor {
private String reflectionsRoot;
private Logger log = LoggerFactory.getLogger(ReflectionsPersistenceUnitPostProcessor.class);
@Override
public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {
Reflections r = new Reflections(this.reflectionsRoot, new TypeAnnotationsScanner());
Set<String> entityClasses = r.getStore().getTypesAnnotatedWith(Entity.class.getName());
Set<String> mappedSuperClasses = r.getStore().getTypesAnnotatedWith(MappedSuperclass.class.getName());
for (String clzz : mappedSuperClasses)
{
pui.addManagedClassName(clzz);
}
for (String clzz : entityClasses)
{
pui.addManagedClassName(clzz);
}
}
public String getReflectionsRoot() {
return reflectionsRoot;
}
public void setReflectionsRoot(String reflectionsRoot) {
this.reflectionsRoot = reflectionsRoot;
}
}
Luego ajusté mi xml de contexto de primavera de esta manera:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="false" />
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
</bean>
</property>
<property name="persistenceUnitName" value="GenericPersistenceUnit"/>
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>
<property name="persistenceUnitPostProcessors">
<list>
<bean class="com.austinmichael.core.repository.ReflectionsPersistenceUnitPostProcessor">
<property name="reflectionsRoot" value="com.austinmichael"/>
</bean>
</list>
</property>
</bean>
Tenga en cuenta el registro de ReflectionsPersistenceUnitPostProcessor
en la configuración persistenceUnitPostProcessors.
Y eso es. Cada clase con una anotación JPA Entity o MappedSuperclass
en classpath se agrega a classpath. Tuve que darle a Reflections el prefijo de un nombre de paquete para escanear, por lo que com.austinmichael
está ahí. Puede registrar un segundo ReflectionsPersistenceUnitPostProcessor
con un prefijo de nombre de paquete diferente si lo desea si sus entidades no comparten un prefijo de nombre de paquete común.
Pero, esto ahora es JPAVendor agnóstico.
No creo que exista tal opción: JPA admite escanear el classpath para entidades o listar explícitamente las clases de entidad en persistence.xml. Sin embargo, como está utilizando hibernate como proveedor de persistencia, siempre puede recurrir al código de hibernación. Eche un vistazo a las clases HibernateEntityManager
e HibernateEntityManagerFactory
. Puede enviar fábricas de administradores de entidades y administradores de entidades y hacer las cosas habituales de hibernación.