java - 从外部 jar 或外部类路径动态加载映射实体

标签 java hibernate groovy classloader

我需要映射 hibernate.cfg.xml 中未列出的实体,这些类是动态加载的 来自仲裁文件夹。我正在尝试注册 ClassLoaderService 来更改加载行为, 如果类在编译时定义并存在于类路径中,则以下代码运行正常,但如果 我尝试映射动态加载的类,但出现 ClassNotFoundException。对于同一问题有一些疑问,但我没有找到任何可行的解决方案。

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 运行,它工作正常,我从服务获取类加载日志。但该服务从未收到 如果我 addAnnotatedClass 是动态加载的(从 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

最佳答案

这对我有用:

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);

关于java - 从外部 jar 或外部类路径动态加载映射实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27304580/

相关文章:

java - 如何制作一个菜单,直到用户输入退出

java - 添加本地目录作为 gradle 依赖项

java - Spring 服务层的 JUnit 测试用例

gradle - Gradle dockerCompose插件为所有任务保留最新配置

jenkins - 如何打印多行字符串参数的每个元素?

java - @autowired 注释如何用于私有(private)字段?

java - 无法从 Java Spring 应用程序连接到 MySQL,即使它可以从控制台运行

java - 无法在 Hibernate Criteria 中获取两个日期之间的数据

java - 如何恢复 Hibernate 中的 transient 字段,如 readResolve() 以进行 hibernate 序列化?

java - 我的 Hibernate CRUD 没有在表中保存数据,而是显示表为空