【问题标题】:How to avoid classloading issues with MyBatis in OSGI environment?如何避免 OSGI 环境中 MyBatis 的类加载问题?
【发布时间】:2013-10-02 15:19:26
【问题描述】:

我正在开发具有多个模块的基于 Eclipse 3.7 RCP 的应用程序。模块 A 是一堆库,包括 mybatis-3.2.2.jar。模块 B 依赖于模块 A(manifest.mf 中的 Require-Bundle)并具有使用 MyBatis 访问数据库中数据的代码。我已经在模块 B 中导出了带有映射器类和 XML 的包,并将它们导入到模块 A 中。我正在代码中构建 SqlSessionFactory,如果我按名称添加所有映射器类,它就可以正常工作,例如

configuration.addMapper(MyMapper.class);

但是,当我尝试在包中添加所有映射器时:

configuration.addMappers(MyMapper.class.getPackage().getName());

MyBatis 没有看到它们。

我尝试更改默认类加载器,但这没有帮助。

Resources.setDefaultClassLoader(this.getClass().getClassLoader());

我怀疑问题与 OSGI 环境中类的可见性有关。如果是这种情况,有什么方法可以在应用程序中修复它?

【问题讨论】:

  • 此外,您可能希望向 mybatis 提交错误,因为他们使用 ResolverUtil 的方式甚至不允许您提供自己的类加载器而无需重新编写扫描代码。至少它立即看起来如何。
  • 我找到了这个链接,它对我很有效techtwitch.blogspot.de/2012/06/…

标签: java eclipse osgi mybatis


【解决方案1】:

你试过了吗

Resources.setDefaultClassLoader(Activator.class.getClassLoader())。我认为这将使用捆绑包的 OSGi 类加载器。希望这会有所帮助。

【讨论】:

    【解决方案2】:

    configuration.addMappers 使用它自己的 ResolverUtil,它使用 Thread 上下文类加载器。 (至少在mybatis3中)。

    最好的办法是编写自己的扫描代码并直接使用 addMapper。下面有我的参考资料和例子:

    http://grepcode.com/file/repo1.maven.org/maven2/org.mybatis/mybatis/3.1.1/org/apache/ibatis/session/Configuration.java?av=f#518

    http://grepcode.com/file/repo1.maven.org/maven2/org.mybatis/mybatis/3.1.1/org/apache/ibatis/io/ResolverUtil.java#148

    编辑:这里有一些适用于 mybatis 3.2.2

    http://grepcode.com/file/repo1.maven.org/maven2/org.mybatis/mybatis/3.2.2/org/apache/ibatis/io/ResolverUtil.java#147

    http://grepcode.com/file/repo1.maven.org/maven2/org.mybatis/mybatis/3.2.2/org/apache/ibatis/binding/MapperRegistry.java#86

    同样的事情也适用。

    【讨论】:

    • 我得出了类似的结论。我可以看到 ResolverUtil.find(Test test, String packageName) 方法甚至不使用类加载器字段,而是委托给 VFS.list(path)。我想我必须编写一个自定义 VFS 类来实现特定于 OSGI 的扫描逻辑。对我来说不值得努力,我会继续一个一个地添加我的 Mapper 类。
    • 即使您的链接可能会将用户重定向到正确答案,但最好在此处解释它们,因为随着时间的推移,您永远不知道链接是否仍然正常运行。谢谢。 @Sheena Artip
    【解决方案3】:

    我在 Felix OSGi 环境中遇到了与 Spring Data JPA 类似的问题。在那种情况下,我能够覆盖一个工厂类并将其添加到有问题的方法中:

    ClassLoader pre = Thread.currentThread().getContextClassLoader();
    try {
        Thread.currentThread().setContextClassLoader(context.getClassLoader());
        // add mappers here or call super method
    } finally {
        Thread.currentThread().setContextClassLoader(pre);
    }
    

    在这种情况下,“上下文”是 Spring 上下文,但您应该能够从 BundleWiring 获取模块 B 的类加载器。

    Bundle bundle; //get this by symbolic name if you don't have a reference
    BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
    bundleWiring.getClassLoader();
    

    希望 addMappers 方法不需要在同一个调用中访问模块 A 的类加载器。如果是这种情况,除非有办法扩展和注入不同的 Configuration 或 MapperRegistry 类,否则您将无能为力。

    【讨论】:

      猜你喜欢
      • 2012-06-01
      • 2012-07-27
      • 2018-08-13
      • 2014-09-04
      • 1970-01-01
      • 1970-01-01
      • 2011-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多