Injecting MyBatis beans
This section will take you through de details of the discovery and injection process.
Producing a Factory
The SqlSessionFactory is the source of any MyBatis bean so first you need to create one (at least)
and let the container know about it existence. To do so, create a bean with producer method, and make sure
that you add the @ApplicationScoped annotation to it because we just want to have one instance
of the factory for the whole application.
In order to let the container identify the producers to be used, you must annotate them with @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
If you forget the @ApplicationScoped the factory will be created on each injection, what implies
parsing and loading the whole MyBatis xml file set. Your application will not fail but it will be terribly slow.
NOTE
If you forget the @SessionFactoryProvider the factory will be ignored by mybatis-cdi.
Disvovering and injecting Mappers
There is nothing special more than injecting the mapper as any other CDI dependecy:
public class FooService {
@Inject UserMapper userMapper;
public User doSomeStuff(String userId) {
return this.userMapper.getUser(userId);
}
}
Then it will get an instance (a proxy in fact) of that mapper from the SqlSessionFactory registered in
the CDI container and inject it into the bean. This proxy is not a normal mapper but a thread safe singleton
so you should not worry about its scope.
Any configuration problem that may happen during the initialization process will make the module throw a
MyBatisCdiConfiurationException. Given that there is not much to configure, this
exception is only thrown when the SqlSessionFactory cannot be found or is misconfigured.
Resolving ambiguities
In case you have more than one SqlSessionFactory you can choose the one you want to use
in any injection point by using:
- One or more qualifiers (defined by you)
- The name of the
SqlSessionFactory(qualified with@Named) - Any paranoid combination of both
Follows below an snippet that shows a producer that creates two SqlSessionFactorys. A qualifier is used
to differentiate them as you would do with any other CDI bean:
@ApplicationScoped
@Produces
@FooQualifier
@SessionFactoryProvider
public SqlSessionFactory createManagerFoo() throws IOException {
...
}
@ApplicationScoped
@Produces
@BarQualifier
@SessionFactoryProvider
public SqlSessionFactory createManagerBar() throws IOException {
...
}
Now that there is no ambiguity you can select what factory you want to inject by adding the qualifier to it:
@Inject @FooQualifier UserMapper userMapper;
You can also give a name to your SqlSessionFactory:
@ApplicationScoped
@Produces
@Named("fooManager")
@SessionFactoryProvider
public SqlSessionFactory createManager() throws IOException {
...
}
And refer to it by its name in an injection point:
@Inject @Named("fooManager") UserMapper userMapper;
Injecting an SqlSession
You can inject a thread safe SqlSession by requesting its injection as follows:
@Inject SqlSession sqlSession;
The factory selection criteria we saw for mappers apply also to SqlSession injection.
NOTE
MyBatis-CDI controls the lifecycle of the injected SqlSession so you must not call any transactional method
like commit() or rollback(), nor any lifecycle method like close().
MyBatis