Introduction to MyBatis-Guice
In our daily work we've been strongly using both MyBatis Sql Mapper and Google Guice frameworks and once noticed we'd been continuosly repeating the same code snippets in different projects, according to the DRY don't repeat yourself principle, we started realizing something that alleviate us the task to create our stuff.
Indeed, this small library intends to create the missing perfect glue between the two popular frameworks, reducing the boilerplate and redundant code that users have to write to configure and use MyBatis into a Google Guice context.
Quick Look
Core components are contained in the org.mybatis.guice package, providing a set of reusable Google Guice com.google.inject.Providers and com.google.inject.Modules that alleviate users the task to create MyBatis objects.
The core component of the Guice approach is represented by the org.mybatis.guice.MyBatisModule that's able to create, through a serie of required and optional com.google.inject.Providers, the core MyBatis, SqlSessionFactory, SqlSessionManager and the user defined Mappers.
Class<? extends Provider<DataSource>> dataSourceProviderClass = [...];
Class<? extends Provider<TransactionFactory>> txFactoryProviderClass = [...];
Injector injector = Guice.createInjector(new MyBatisModule() {
@Override
protected void initialize() {
bindDataSourceProviderType(dataSourceProviderClass);
bindTransactionFactoryType(txFactoryProviderClass);
addMapperClass(ContactMapper.class);
handleType(CustomType.class).with(CustomLongTypeHandler.class);
handleType(Address.class).with(AddressTypeHandler.class);
addInterceptorClass(CountUpdateInterceptor.class);
addSimpleAlias(com.acme.Foo.class);
addAlias("MyBar", com.acme.Bar.class);
handleType(com.acme.Foo.class).with(com.acme.dao.FooHandler.class);
handleType(com.acme.Bar.class).with(com.acme.dao.BarHandler.class);
addMapperClass(com.acme.dao.FooMapper.class);
addMapperClass(com.acme.dao.BarMapper.class);
lazyLoadingEnabled(true);
bindObjectFactoryType(com.acme.MyObjectFactoryProvider.class);
}
});Once the MyBatis module has been set-up, clients are ready to request MyBatis components injections.
For example, users can request directly the configured Mapper interfaces:
@Singleton
public final class MyMappersClient {
@Inject
private FooMapper fooMapper;
@Inject
private BarMapper barMapper;
// setters here
@Transactional(
executorType = ExecutorType.BATCH,
isolationLevel = TransactionIsolationLevel.READ_UNCOMMITTED,
rethrowExceptionsAs = MyCustomException.class,
exceptionMessage = "Something went wrong while foobaring {0} argument"
)
public void doFooBar(String arg) {
this.fooMapper.doFoo(arg);
this.barMapper.doBar(arg);
}
Please refer to the reference manual to know all about MyBatis-Guice features
Installation
Installing the MyBatis-Guice module it is very easy, just put the mybatis-guice-3.2.jar and related dependencies in the classpath!
Apache Maven users instead can easily adding the following dependency in their POMs :
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-guice</artifactId>
<version>3.2</version>
</dependency>
Is there any advantage of using this library over Creating a guice session factory provider(as a Singleton) and injecting the same and then then create session, mappers as usual?
Josh.
@joshnet2030: the main advantages are 1) avoid repeating the same code every time you need such integration 2) reusing stuff already tested. I'd like to invite you to take a look at the user manual (http://mybatis.googlecode.com/files/mybatis-guice-1.0.0-reference.pdf) to see the complete features set
Wow. i get the point now after reading the reference guide. I have actually deprecated all my daos and am using the mapper interfaces directly. Adding a now functionality is as easy as creating the mapper and the sql.
Just one little question - Is this project officially part of the Mybatis project?
Thanks guys.
Josh
Yes its part of mybatis, josh if you didnt discovered it by now. Just as the spring integration.
From reference:
Just checked source, this looks like:
if (TransactionIsolationLevel.NONE == transactional.isolationLevel()) { this.sqlSessionManager.startManagedSession(transactional.executorType(), transactional.autoCommit()); } else { this.sqlSessionManager.startManagedSession(transactional.executorType(), transactional.isolationLevel()); }So there is no way to pass TransactionIsolationLevel??.NONE all the way up to the connection? Why default value for isolationLevel isnt null (now it is TransactionIsolationLevel?.NONE)?
Hi. This has been recently changed in trunk. Have a look at it.