Jestem późno do partii, ale myślę, że będzie to zaoszczędzić trochę ludziom trochę głowa. Zaimplementowałem skanowanie ze ścieżkami klas czystego JPA (bez potrzeby użycia sprężyny), które integruje się z np. guice-persist również w razie potrzeby.
Oto, co musisz zrobić.
pierwsze, zmienić persistence.xml i dodać własną implementację, jak:
<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>
W celu dla dostawców, aby uznać, trzeba będzie zrobić to wykrywalne. JPA odkrywa użyciu mechanizmu ładowania usługa, więc dodajemy:
/src/main/resources/META-INF/services/javax.persistence.spi.PersistenceProvider
Plik ten ma dokładnie jedną linię:
my.custom.package.HibernateDynamicPersistenceProvider
Wreszcie dodać własne dostawcy i oprzeć go na HibernateProvider (Opieram to na tym, ponieważ chcę użyć hibernacji):
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;
}
}
musiałem zastąpić 2 sposoby, pierwszy:
protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilder(
PersistenceUnitDescriptor persistenceUnitDescriptor, Map integration, ClassLoader providedClassLoader)
To jest metoda przechwytywania. Dodałem niestandardową właściwość "CUSTOM_CLASSES", która naprawdę powinna być nazwana "CUSTOM_PACKAGES", która wyświetli wszystkie pakiety, które muszą zostać przeskanowane. W tym momencie jestem trochę leniwy i pomijam skanowanie rzeczywistej ścieżki klasowej, ale możesz to zrobić samemu - to całkiem proste. Następnie możesz zadzwonić pod numer
tmp.addClasses("class1", "class2");
Gdzie klasy są tymi, które odkryłeś.
Druga metoda jesteśmy nadrzędnym jest:
protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilderOrNull(String persistenceUnitName, Map properties, ClassLoader providedClassLoader)
To dlatego, że jesteśmy dostawcą rozszerzenie jest ustalony, aby umożliwić tylko zajęcia hibernacji w celu utworzenia EMF. Ponieważ mamy niestandardową klasę przechwytującą konstrukcję, nasze nazwy nie sumują się. Dodałem więc:
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;
}
To rozszerza normalny test hibernacji, aby mój operator niestandardowy był ważny.
Wola, skończymy, masz teraz włączoną funkcję hibernacji, skanowanie klasy z JPA.
Czy możesz podać mi informacje, jak skonfigurować Hibernate, aby akceptować jednostki bez ich deklarowania? Wygląda na to, że nie jest to zachowanie domyślne. – Rafal
Przepraszam za zaniedbanie, po próbie na innym Tomku działało jak czar.Jest to domyślne zachowanie i myślę, że zostało spowodowane z powodu wtyczki gradle-tomcat>. < – lucasvc