I use Spring Boot, Spring Data JPA and Hibernate.
I need to filter entities which are managed by EntityManager
by custom annotation. LocalContainerEntityManagerFactoryBean
allows to set a list of packages which are scanned but filters seems to be hardcoded in DefaultPersistenceUnitManager
.
Otherwise LocalSessionFactoryBuilder
(Hibernate specific) has this feature (method setEntityTypeFilters
) but can't be used with Spring Data JPA Repositories which require EntityManagerFactory
.
How can I apply entity filtering to LocalContainerEntityManagerFactoryBean
?
I had a similar problem: I want to "exclude" some Entities while still using package scanning provided by LocalContainerEntityManagerFactoryBean
. In my case, I wanted to make use of @Profile(...)
annotation used by spring since I need certain entities only if a specific profile is active.
I solved it by implementing a PersistenceUnitPostProcessor
which removes classes that were added by the scanner. It might not be the most elegant solution, but it works (Spring 4.1.2).
public class ProfileAwarePersistenceUnitPostProcessor implements PersistenceUnitPostProcessor {
@Autowired
Environment environment;
/**
* Post process the persistence unit and remove Entity classes that require a specific spring profile
* if profile is not active.
*
* @param pui The persistence unit that was put together so far.
* @see org.springframework.orm.jpa.persistenceunit.PersistenceUnitPostProcessor#postProcessPersistenceUnitInfo(org.springframework.orm.jpa.persistenceunit.MutablePersistenceUnitInfo)
*/
@Override
public void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {
// Check for null to be sure.
if (pui.getManagedClassNames() != null) {
Iterator<String> iterator = pui.getManagedClassNames().iterator();
while (iterator.hasNext()) {
String className = iterator.next();
try {
Class<?> entityClass = Class.forName(className);
Profile profileAnnotation = entityClass.getAnnotation(Profile.class);
if (profileAnnotation != null) {
String[] requiredProfiles = profileAnnotation.value();
if (!environment.acceptsProfiles(requiredProfiles)) {
Logging.debug("Removing class " + className + " from persistence unit since none of the required profiles is active "
+ StringUtils.join(", ", requiredProfiles));
iterator.remove();
}
}
} catch (ClassNotFoundException e) {
// Something must have gone wrong during scanning if class is suddenly not found anymore.
Logging.warn("Class " + className + " not found while post processing persistence unit.", e);
}
}
}
}
}
Any other annotation can be used instead of Profile.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With