2014-12-04 66 views
0

我需要映射未在hibernate.cfg.xml中列出的實體,這些類從仲裁文件夾動態加載 。我試圖註冊一個ClassLoaderService來改變加載行爲, 下面的代碼運行良好,如果類在編譯時定義並存在於類路徑中,但如果我試圖映射一個dinamically加載的類,我得到ClassNotFoundException。有關於同一問題的一些問題,但我沒有找到任何工作解決方案。Map實體從外部jar或外部類路徑動態加載

URL file = ConsultaBase.class.getProtectionDomain().getCodeSource().getLocation().toURI().resolve("implementacao/").resolve("hibernate.cfg.xml").toURL(); 
Configuration configuration = new Configuration() 
    .addAnnotatedClass(Registro.class).configure(file);   

ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder (
    new BootstrapServiceRegistryImpl(
     new ClassLoaderServicePirilampo(Registro.class.getClassLoader()), 
     new LinkedHashSet<Integrator>() 
    ) 
) 
.applySettings(configuration.getProperties()) 
.addService(ClassLoaderService.class, new ClassLoaderServicePirilampo()) 
.build(); 

//this line throws ClassNotFoundException 
sessionFactory = configuration.buildSessionFactory(serviceRegistry);  

我延長了ClassLoaderServiceImpl才能登錄請求的類,並注意到從JUnit的運行,從那裏類中定義的項目,它工作得很好,我從服務類加載日誌。但是,如果我添加了已加載的消息(來自GroovyClassLoader),則該服務從不會收到對同一類的請求 。

最後一行拋出去如下因素的錯誤:

17:06:49 ERROR [AssertionFailure] HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): java.lang.ClassNotFoundException: implementacao.Registro 
PersistentClass name cannot be converted into a Class 
org.hibernate.AssertionFailure: PersistentClass name cannot be converted into a Class 
    at org.hibernate.cfg.BinderHelper.getPropertyOverriddenByMapperOrMapsId(BinderHelper.java:817) 
    at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2169) 
    at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:963) 
    at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:796) 
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3788) 
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3742) 
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1410) 
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844) 
    at implementacao.ConsultaBase.createSessionFactory(ConsultaBase.java:64) 
    at implementacao.ConsultaBase.consultar(ConsultaBase.java:92) 
    at implementacao.ConsultaBase$consultar.call(Unknown Source) 
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45) 
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108) 
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112) 
    at ConsultaBaseConector.run(ConsultaBaseConector.groovy:6) 
    at groovy.util.GroovyScriptEngine.run(GroovyScriptEngine.java:551) 
    at br.org.fplf.processo.maquinaexecucao.parser.ParserAtividadeAutomatica.executar(ParserAtividadeAutomatica.java:43) 
    at br.org.fplf.processo.maquinaexecucao.MaquinaExecucao.executarAtividadeAutomatica(MaquinaExecucao.java:1050) 
    at br.org.fplf.processo.maquinaexecucao.MaquinaExecucao.executarAtividadeFluxo(MaquinaExecucao.java:973) 
    at br.org.fplf.processo.maquinaexecucao.MaquinaExecucao.executar(MaquinaExecucao.java:646) 
    at br.org.fplf.processo.maquinaexecucao.MaquinaExecucao.run(MaquinaExecucao.java:368) 
Caused by: java.lang.ClassNotFoundException: implementacao.Registro 
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1702) 
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1547) 
    at java.lang.Class.forName0(Native Method) 
    at java.lang.Class.forName(Unknown Source) 
    at org.hibernate.annotations.common.util.ReflectHelper.classForName(ReflectHelper.java:60) 
    at org.hibernate.annotations.common.reflection.java.JavaReflectionManager.classForName(JavaReflectionManager.java:138) 
    at org.hibernate.cfg.BinderHelper.getPropertyOverriddenByMapperOrMapsId(BinderHelper.java:813) 
    ... 20 more 

回答

1

這爲我工作:

Thread.currentThread().setContextClassLoader(DynamicallyLoadedClass.getClassLoader());  

例如:

URL file = ConsultaBase.class.getProtectionDomain().getCodeSource().getLocation() 
    .toURI().resolve("hibernate.cfg.xml").toURL(); 

Configuration configuration = new Configuration() 
    .addAnnotatedClass(Registro.class).configure(file);   

ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() 
    .applySettings(configuration.getProperties()) 
    .build(); 

Thread.currentThread().setContextClassLoader(Registro.class.getClassLoader()); 

sessionFactory = configuration.buildSessionFactory(serviceRegistry); 
+0

.setContextClassLoader(...)似乎解決問題是如果我從一個位置添加課程,但如果我在不同文件夾/罐子中有很多課程,該怎麼辦?然後再次更改ContextClassLoader將在先前加載的類中導致ClassNotFoundException。我如何「添加上下文」而不是改變它? – ANTARA 2015-08-27 11:58:30

+0

我會在我的代碼中檢查這一點,我沒有看到它一段時間。但是,實際上,我從不同的文件夾加載類別 ,這些類甚至可以具有相同的名稱。我猜在sessionFactory構建完成後setContextClassLoader會不會影響到它? 呢? 呢? – Gus 2015-08-27 13:05:17

+0

不完全。我爲配置添加了兩個帶註釋的類:module1.jar中的Registro1.class和module2.jar中的Registro2.class。然後,如果.setContextClassLoader(Registro1.class ...)在.buildSessionFactory(...)之前,那麼Hibernate會在嘗試加載Registro2.class時拋出ClassNotFoundException。 – ANTARA 2015-08-27 21:32:07