注入 MyBatis 组件

本节将带你详细了解发现和注入的过程。

创建一个工厂

SqlSessionFactory 是 MyBatis 组件的开始,因此首先需要创建它, 并让容器知道它的存在。 要做到这一点,请使用 producer 方法创建一个组件,并确保添加了 @ApplicationScoped 注解。因为我们只希望在整个应用程序中拥有一个工厂的实例。

为了让容器标识要使用的生产者,你必须用 @SessionFactoryProvider

public class MyProducers {

  @Produces
  @ApplicationScoped
  @SessionFactoryProvider
  public SqlSessionFactory produceFactory() {
    String resource = "org/mybatis/example/mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    return sqlSessionFactory;
  }

}

NOTE 如果你忘记添加 @ApplicationScoped,工厂将在每次注入时创建,这意味着将解析和加载所有的 MyBatis xml 文件。你的应用程序不会有问题,但速度会非常慢。

NOTE 如果你忘记了 @SessionFactoryProvider,该工厂将被 mybatis-cdi 忽略。

发现和注入映射器

没有什么比将映射器作为 CDI 依赖注入更特别的了:

public class FooService {

  @Inject UserMapper userMapper;

  public User doSomeStuff(String userId) {
    return this.userMapper.getUser(userId);
  }

}

然后,它将从 CDI 容器中注册的 SqlSessionFactory 中获取该映射器的实例(实际上是代理) ,并将其注入到组件中。这个代理不是一个普通的映射器,而是一个线程安全的单例,所以你不需要担心它的作用域。

在初始化过程中可能发生的任何配置问题都会使模块抛出 MyBatisCdiConfiurationException。考虑到没有太多需要配置的东西,只有当 SqlSessionFactory 找不到或配置错误时,才会抛出此异常。

解决歧义

如果有多个 SqlSessionFactory,则可以使用以下方法选择要在任何注入点中使用的一个:

  • 使用一个或多个限定符(由你定义)
  • SqlSessionFactory 命名(使用 @Named 注解)
  • 还可以将它们组合使用

下面是一个代码段,该代码段创建了两个 SqlSessionFactory 的 producer。限定符用于区分它们,就像处理任何其他 CDI 组件一样:

@ApplicationScoped
@Produces
@FooQualifier
@SessionFactoryProvider
public SqlSessionFactory createManagerFoo() throws IOException {
  ...
}

@ApplicationScoped
@Produces
@BarQualifier
@SessionFactoryProvider
public SqlSessionFactory createManagerBar() throws IOException {
  ...
}

现在没有歧义了,你可以通过向其添加限定符来选择要注入的工厂:

@Inject @FooQualifier UserMapper userMapper;

你还可以为 SqlSessionFactory 命名:

@ApplicationScoped
@Produces
@Named("fooManager")
@SessionFactoryProvider
public SqlSessionFactory createManager() throws IOException {
  ...
}

在注入点中用它的名字来代替它:

@Inject @Named("fooManager") UserMapper userMapper;

注入 SqlSession

你可以通过请求注入线程安全的 SqlSession,如下所示:

@Inject SqlSession sqlSession;

我们看到的映射器的工厂选择标准也适用于 SqlSession 注入。

NOTE MyBatis-CDI 控制注入的 SqlSession 的生命周期,因此你不能调用任何事务方法,如 commit()rollback()。也没有像 close() 这样的生命周期方法。