llego tarde a la fiesta, pero creo que esto va a salvar algunas personas un poco de dolor de cabeza. Implementé el escaneo classpath para JPA puro (no se necesita primavera, etc.) que se integra con, p. guice-persist si es necesario también.
Esto es lo que necesita hacer.
En primer lugar, cambiar la persistence.xml y añadir su propia aplicación, como:
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="my.persistence.unit" transaction-type="RESOURCE_LOCAL">
<provider>my.custom.package.HibernateDynamicPersistenceProvider</provider>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<property name="hibernate.max_fetch_depth" value="30" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="true" />
</properties>
</persistence-unit>
A fin de que los proveedores de ser reconocido, tendrá que hacerla visible. JPA descubre el uso del mecanismo de carga de servicio, por lo que añadir:
/src/main/resources/META-INF/services/javax.persistence.spi.PersistenceProvider
Este archivo tiene exactamente una línea:
my.custom.package.HibernateDynamicPersistenceProvider
Por último añadir su propio proveedor y basarlo en la HibernateProvider (Me baso en ese ya que quiero utilizar hibernación):
public class HibernateDynamicPersistenceProvider extends HibernatePersistenceProvider implements PersistenceProvider {
private static final Logger log = Logger.getLogger(HibernateDynamicPersistenceProvider.class);
public static final String CUSTOM_CLASSES = "CUSTOM_CLASSES";
@Override
protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilder(
PersistenceUnitDescriptor persistenceUnitDescriptor, Map integration, ClassLoader providedClassLoader) {
if(persistenceUnitDescriptor instanceof ParsedPersistenceXmlDescriptor) {
ParsedPersistenceXmlDescriptor tmp = (ParsedPersistenceXmlDescriptor) persistenceUnitDescriptor;
Object object = integration.get("CUSTOM_CLASSES");
}
return super.getEntityManagerFactoryBuilder(persistenceUnitDescriptor, integration, providedClassLoader);
}
protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilderOrNull(String persistenceUnitName, Map properties, ClassLoader providedClassLoader) {
log.debug(String.format("Attempting to obtain correct EntityManagerFactoryBuilder for persistenceUnitName : %s", persistenceUnitName));
final Map integration = wrap(properties);
final List<ParsedPersistenceXmlDescriptor> units;
try {
units = PersistenceXmlParser.locatePersistenceUnits(integration);
}
catch (Exception e) {
log.debug("Unable to locate persistence units", e);
throw new PersistenceException("Unable to locate persistence units", e);
}
log.debug(String.format("Located and parsed %s persistence units; checking each", units.size()));
if (persistenceUnitName == null && units.size() > 1) {
// no persistence-unit name to look for was given and we found multiple persistence-units
throw new PersistenceException("No name provided and multiple persistence units found");
}
for (ParsedPersistenceXmlDescriptor persistenceUnit : units) {
log.debug(String.format(
"Checking persistence-unit [name=%s, explicit-provider=%s] against incoming persistence unit name [%s]",
persistenceUnit.getName(),
persistenceUnit.getProviderClassName(),
persistenceUnitName
));
final boolean matches = persistenceUnitName == null || persistenceUnit.getName().equals(persistenceUnitName);
if (!matches) {
log.debug("Excluding from consideration due to name mis-match");
continue;
}
// See if we (Hibernate) are the persistence provider
String extractRequestedProviderName = ProviderChecker.extractRequestedProviderName(persistenceUnit, integration);
if (! ProviderChecker.isProvider(persistenceUnit, properties) && !(this.getClass().getName().equals(extractRequestedProviderName))) {
log.debug("Excluding from consideration due to provider mis-match");
continue;
}
return getEntityManagerFactoryBuilder(persistenceUnit, integration, providedClassLoader);
}
log.debug("Found no matching persistence units");
return null;
}
}
tuve que sobrescribir los métodos 2, en primer lugar:
protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilder(
PersistenceUnitDescriptor persistenceUnitDescriptor, Map integration, ClassLoader providedClassLoader)
Este es el método de interceptación. Agregué una propiedad personalizada "CUSTOM_CLASSES" que realmente debería llamarse "CUSTOM_PACKAGES" que enumerará todos los paquetes que necesitan ser escaneados. En este punto, soy un poco vago y omitiré el escaneo del classpath actual, pero puede hacerlo usted mismo, es bastante directo. A continuación, puede llamar al
tmp.addClasses("class1", "class2");
Donde las clases son las que descubrió.
El segundo método que estamos primordial es:
protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilderOrNull(String persistenceUnitName, Map properties, ClassLoader providedClassLoader)
Esto es porque el proveedor estamos extendiendo es codificado a sólo permiten clases de hibernación para crear un EMF. Como tenemos una clase personalizada que intercepta la construcción, nuestros nombres no se suman. Así que agregué:
String extractRequestedProviderName = ProviderChecker.extractRequestedProviderName(persistenceUnit, integration);
if (! ProviderChecker.isProvider(persistenceUnit, properties) && !(this.getClass().getName().equals(extractRequestedProviderName))) {
log.debug("Excluding from consideration due to provider mis-match");
continue;
}
Esto amplía la verificación de hibernación normal para incluir también mi proveedor personalizado para que sea válido.
Wola, hemos terminado, ahora tiene hibernate habilitado escaneado classpath con JPA.
¿Podría darme información sobre cómo configurar Hibernate para aceptar entidades sin declararlas? Parece que esto no es un comportamiento predeterminado. – Rafal
Lo siento por la votación negativa, después de probar con otro Tomcat funcionó como un encanto.Es un comportamiento predeterminado y creo que fue causado por el plugin gradle-tomcat>. < – lucasvc