问题
Is there a way to use programmatic configuration provided by Ejb3Configuration with container managed entity management? I would like to dynamically add (additional) annotated classes that were discovered via ServiceLoader after the persistence.xml is processed.
I attempted to extend HibernatePersistence override the createContainerEntityManagerFactory method where I added the functionality to add the classes but I found two problems: 1) When I attempt to call the EjbConfiguration instances configure(PersistenceUnitInfo, Map) method within the new PersistenceProvider, I get null returned. 2) I get a NPE thrown by my app server (both GF 3.0.1 and GF 3.1) at application shutdown originating from either org.glassfish.persistsnce.jpa.JPAApplicationContainer.closeAllEMFs or org.glassfish.persistence.jpa.JPADeployer.closeEMFs, respectively
The following is my PersistenceProvider:
//left out createEntityManagerFactory for brevity
public class DynamicEntityProvider extends HibernatePersistence {
@Override
public EntityManagerFactory createContainerEntityManagerFactory
(PersistenceUnitInfo info, Map props) {
final Ejb3Configuration config = new Ejb3Configuration();
final Ejb3Configuration configured = config.configure(info, props);
if (configured != null) {
//never gets here, configured is always returned null
addDynamicEntities(configured);
return configured.buildEntityManagerFactory();
}
//logging code which notifies me that configured was null
return null;
}
//addDynamicEntities() method impl
I simply replace the tag in my persistence.xml file to the class and it does indeed get called as expected...just with the problems listed above =)
Any ideas would be greatly appreciated!
回答1:
I don't know if you already have solved your issue, but...
It returns null because the HibernatePersistence class that you are extending checks if the persistence.xml has the provider set to it not a subclass, so it doesn't recognize your class(DynamicEntityProvider) as the provider so it doesn't parse your xml.
if ( metadata.getProvider() == null || IMPLEMENTATION_NAME.equalsIgnoreCase(metadata.getProvider()) ) {
Where IMPLEMENTATION_NAME is
private static final String IMPLEMENTATION_NAME = HibernatePersistence.class.getName();
You can change it internally via reflection but it is not a "good" way of doing that.
回答2:
It looks like some kind of classloader visibility issue. I know GF uses OSGi bundling so I'm not entirely surprised.
Basically config.configure returns null if it does not find that the persistence unit described by info matches the persistence provider at play. Try and display info and see if the persistence provider is correctly set up and watch for classloader issues (ie myClass != yourClass if the CL loading it is not the same)
来源:https://stackoverflow.com/questions/6229745/using-hibernate-ejb3configuration-with-container-management