【问题标题】:MyBatis CDI beanManager.getBeans fails to find SqlSessionFactory bean in GlassFish 4 and 4.1MyBatis CDI beanManager.getBeans 在 GlassFish 4 和 4.1 中找不到 SqlSessionFactory bean
【发布时间】:2015-04-05 17:44:09
【问题描述】:

我创建了一个简单的 Java EE 程序来试验 MyBatis,但我在使用 MyBatis CDI 模块时遇到了问题。我已按照http://mybatis.github.io/cdi/injection.html 中概述的说明进行操作,但是当我的程序尝试使用 MyBatis 时,会引发 MybatisCdiConfigurationException 异常,描述为“没有正确配置 SqlSessionFactory 生产者。”

我正在使用的 SqlSessionFactory 的代码如下:

import javax.annotation.Resource;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.sql.DataSource;

import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;

public class SqlSessionFactoryProvider {

    @Resource (name="jdbc/MyDatabase")
    DataSource dataSource;

    @Produces
    @ApplicationScoped
    public SqlSessionFactory produceFactory() {
        TransactionFactory transactionFactory = new JdbcTransactionFactory();
        Environment environment = new Environment("development",
                transactionFactory, dataSource);
        Configuration configuration = new Configuration(environment);
        configuration.addMapper(ToDoItemMapper.class);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(configuration);
        return sqlSessionFactory;
    }
}

我单步调试了 MyBatis CDI 模块的代码,发现当执行CDIUtils findSqlSessionFactory(...) 中的以下代码行时,它无法找到任何返回SqlSessionFactory.class. 的bean

beans = beanManager.getBeans(SqlSessionFactory.class, qualifiers.toArray(new Annotation[]{}));

我尝试在 GlassFish 4 和 4.1 上运行我的程序,它们都有同样的问题,但如果我在 WildFly 8.1 上运行我的程序,它就可以工作。我的第一个想法是 Glassfish 随附的 Weld 版本可能存在问题,但事实证明 GlassFish 4.1 运行的是 Weld 版本 2.2.2,而 WildFly 运行的是 Weld 版本 2.1.2。

当在 GlassFish 中运行时,我可以在 GlassFish、我的代码或 MyBatis CDI 模块中做些什么来克服这个问题?或者,任何人都可以建议我可以做些什么来进一步调查这个问题吗?

【问题讨论】:

    标签: java glassfish cdi mybatis weld


    【解决方案1】:

    我在尝试实现在 Jboss Wildfly 中运行的 mybatis-CDI 时遇到了同样的问题。我在浏览这个 git smaple 项目时找到了解决方案:https://github.com/artplastika/mybatis-cdi-example

    您似乎唯一缺少的是 SqlSessionFactoryProvider.java 类上的 @Local、@Stateless 和 @Named 注释

    参见 Git 示例中的 SqlSessionFactoryProvider.java 类:https://github.com/artplastika/mybatis-cdi-example/blob/master/mybatis-cdi-example-ejb/src/main/java/org/mybatis/cdi/example/beans/SqlSessionFactoryProviderImpl.java

    您还应该确保 src/main/resources/META-INF 文件夹中有 beans.xml

    编辑

    我的 Maven 依赖设置:

    <dependencies>
            <dependency>
                <groupId>javax</groupId>
                <artifactId>javaee-api</artifactId>
                <version>7.0</version>
                <scope>compile</scope>
            </dependency>
            <!-- Import the CDI API -->
            <dependency>
                <groupId>javax.enterprise</groupId>
                <artifactId>cdi-api</artifactId>
                <version>1.2</version>
                <scope>compile</scope>
            </dependency>
            <!-- Mybatis Dependencies -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.2.5</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-cdi</artifactId>
                <version>1.0.0-beta1</version>
                <scope>compile</scope>
            </dependency>
            <!-- Below Dependencies are very specific to Jboss due to class conflicts if you dont have the exclusions specified -->
            <!-- Proxy support (Mandatory) -->
            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <scope>compile</scope>
                <version>2.2.2</version>
                <exclusions>
                    <exclusion>
                        <groupId>asm</groupId>
                        <artifactId>asm</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <!-- Internal dependency (Required) -->
            <dependency>
                <groupId>org.ow2.asm</groupId>
                <artifactId>asm-util</artifactId>
                <version>5.0.3</version>
                <scope>compile</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.ow2.asm</groupId>
                        <artifactId>asm</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <!-- Internal dependency (Required) -->
            <dependency>
                <groupId>opensymphony</groupId>
                <artifactId>oscache</artifactId>
                <version>2.4</version>
                <scope>compile</scope>
                <!-- This excludes the transitive dependency on JMS -->
                <exclusions>
                    <exclusion>
                        <groupId>javax.jms</groupId>
                        <artifactId>jms</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    

    我的工厂生产者示例如下:

    @Stateless
    @Local(SampleSqlSessionFactoryProvider.class)
    public class SampleSqlSessionFactoryProvider {
        @Produces
        @ApplicationScoped
        @Named("sqlSessionFactory")
        public SqlSessionFactory produceFactory() throws Exception {        
            Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
            SqlSessionFactory sqlSessionFactory = null;
            String environment = "default";
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader, environment);
            return sqlSessionFactory;
        }
    }
    

    为了使用它,我将其注入如下:

    @Local(DaoBean.class)
    @Stateless
    public class DoaBean{
         private @Inject @Named("sqlSessionFactory") SqlSession session;
         public void doStuff(){
             session.selectOne(...);
         }
         ...
    }
    

    【讨论】:

    • 我刚刚尝试添加@Local@Stateless@Named 注释,但我仍然收到MybatisCdiConfigurationException。您使用的是哪个版本的 GlassFish 和 Weld?
    • 我正在使用 JBoss Wildfly (8.2)。如果您仍然收到该错误,则可能与您尝试注入 org.apache.ibatis.session.SqlSession 的方式有关。或者,它可能是类路径问题的某种排列。你的项目是 maven 吗?
    • 奇怪的是我可以做到@Inject private SqlSession sqlSession; 并且SqlSession bean 被很好地注入并且我使用MyBatis 运行查询。只有当我尝试注入 Mapper bean 时才会出现问题。例如,@Inject @Mapper private ToDoItemMapper toDoItemMapper; 会导致MybatisCdiConfigurationException 异常被抛出,因为CDIUtils.findSqlSessionFactory(...) 找不到返回SqlSessionFactory 的工厂方法
    【解决方案2】:

    我找到了解决此问题的方法,但并不是我希望的真正解决方案。我已经将组成 mybatis-cdi 的各种类直接复制到我的程序中,并在META-INF/services/javax.enterprise.inject.spi.Extension 中注册了扩展,现在我可以成功地将映射器注入我的程序并使用 MyBatis 运行查询。

    我已在 MyBatis-CDI GitHub 存储库中将此作为 issue 提出,如果有修复,我将更新此答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-03-02
      • 2017-04-28
      • 2017-11-26
      • 2015-02-13
      • 2019-04-07
      • 2013-09-15
      • 1970-01-01
      相关资源
      最近更新 更多