Introduction

Core components are contained in the org.mybatis.guice.* package, providing a set of reusable Google Guice jakarta.inject.Providers and com.google.inject.Modules that alleviate users the task to create MyBatis objects.

MyBatis Bootstrap

MyBatis offers an excellent APIs layer for the Bootstrap configuration that makes it easy to write custom bootstrap - by default MyBatis comes with the XML loader - and integrating 3rd part components.

The core component of the Guice approach is represented by the org.mybatis.guice.MyBatisModule that's able to create the core MyBatis org.apache.ibatis.session.SqlSessionFactory, org.apache.ibatis.session.SqlSessionManager and the user defined Mappers.

The best way to start is just adding the org.mybatis.guice.MyBatisModule into the com.google.inject.Injector as shown in the example below and explain details step by step:

Class<? extends Provider<DataSource>> dataSourceProviderType = [...];

Class<? extends TransactionFactory> txFactoryClass = [...];

Injector injector = Guice.createInjector(
    new MyBatisModule() {

        @Override
        protected void initialize() {
            environmentId("development");
            bindDataSourceProviderType(dataSourceProviderType);
            bindTransactionFactoryType(txFactoryClass);
        }

    },
    ...
);

SqlSessionFactory sessionFactory = injector.getInstance(SqlSessionFactory.class);
SqlSessionManager sessionManager = injector.getInstance(SqlSessionManager.class);
MyMapper mapper = injector.getInstance(MyMapper.class);
Let's have a look now at the MyBatis module components and features:

MyBatis properties

By design, we choose to reuse the default configuration properties provided by Guice to let users feel free to read and set them in any way you prefer; we suggest to put it in a properties file, maybe filtered and set depending on which environment users are building the application.

By default, if a configuration property is not specified, it will be ignored and MyBatis will take care about proper default initialization. Users can initialize properties using the proper setters OR by following method (please don't bind properties twice!):

binder.bindConstant()
    .annotatedWith(Names.named("mybatis.configuration.XXX"))
    .to(XXXvalue);

The MyBatis module supports the following parameters:

org.mybatis.guice.MyBatisModule properties
Property Setter Default
mybatis.environment.id environmentId(String) Not set, it is required
mybatis.configuration.lazyLoadingEnabled lazyLoadingEnabled(boolean) false
mybatis.configuration.aggressiveLazyLoading aggressiveLazyLoading(boolean) true
mybatis.configuration.multipleResultSetsEnabled multipleResultSetsEnabled(boolean) true
mybatis.configuration.useGeneratedKeys useGeneratedKeys(boolean) false
mybatis.configuration.useColumnLabel useColumnLabel(boolean) true
mybatis.configuration.cacheEnabled useCacheEnabled(boolean) true
mybatis.configuration.defaultExecutorType executorType(ExecutorType) ExecutorType.SIMPLE
mybatis.configuration.autoMappingBehavior autoMappingBehavior(AutoMappingBehavior) AutoMappingBehavior.PARTIAL
mybatis.configuration.failFast failFast(boolean) false

The DataSource Provider

The javax.sql.DataSource Provider is one of the two required providers that takes care about building and injecting the used javax.sql.DataSource.

The mybatis-guice framework comes with some providers that support the MyBatis-native Data Sources and other well known Data Sources, C3P0, Apache Commons DBCP and HikariCP but users are free to implement their own javax.sql.DataSource Provider and reference it in the org.mybatis.guice.MyBatisModule.

Please read the following chapter Data Source Providers to obtain more informations about natively supported providers.

The Transaction Factory

Users are free to plug their preferred org.apache.ibatis.transaction.TransactionFactory:

Class<? extends org.apache.ibatis.transaction.TransactionFactory> txFactoryType = ...

Module module = new MyBatisModule() {

    @Override
    protected void initialize() {
        ...
        bindTransactionFactoryType(txFactoryType);
        ...
    }

}

Configuring aliases

Once users create the org.mybatis.guice.MyBatisModule.Builder, it's quite easy plugging optional MyBatis components, like aliases: here users can define simple aliases, for example Foo that stands for com.acme.Foo, or custom aliases, for example MyFoo that stands for com.acme.Foo.

We found it very useful to add simple aliases because it helped us reduce errors during development; just call:

MyBatisModule module = new MyBatisModule() {

    @Override
    protected void initialize() {
        ...
        addSimpleAlias(com.acme.Foo.class);
        addSimpleAlias(com.acme.Bar.class);
        addSimpleAlias(...);
        ...
    }

}

If you prefer custom aliases, just invoke:

MyBatisModule module = new MyBatisModule() {

    @Override
    protected void initialize() {
        ...
        addAlias("MyFoo").to(com.acme.Foo.class);
        addAlias("MyBar").to(com.acme.Bar.class);
        ...
    }

}

Configuring Type Handlers

Users can also configure type handlers: given the com.acme.Foo type, that has to be handled by the type handler com.acme.dao.FooHandler, just invoke

MyBatisModule module = new MyBatisModule() {

    @Override
    protected void initialize() {
        ...
        handleType(com.acme.Foo.class).with(com.acme.dao.FooHandler.class);
        handleType(com.acme.Bar.class).with(com.acme.dao.BarHandler.class);
        ...
    }

}
and let Google Guice create the handlers instances and bind them to be injected to MyBatis components. Constructor injection will not work, so use field or setter injection for type handler dependencies.

Configuring Interceptor Plugins

Users can easily add their preferred org.apache.ibatis.plugin.Interceptor by invoking:

MyBatisModule module = new MyBatisModule() {

    @Override
    protected void initialize() {
        ...
        addInterceptorClass(com.acme.dao.FooInterceptor.class);
        addInterceptorClass(com.acme.dao.BarInterceptor.class);
        ...
    }

}
and let Google Guice create the interceptors instances and bind them to be injected to MyBatis components.

Configuring Mappers

Users can add Mapper classes to the module by invoking:

MyBatisModule module = new MyBatisModule() {

    @Override
    protected void initialize() {
        ...
        addMapperClass(com.acme.dao.FooMapper.class);
        addMapperClass(com.acme.dao.BarMapper.class);
        ...
    }

};
and let Google Guice create the mappers instance and bind them to be injected to MyBatis components.

Configuring the Object Factory

Simply define your own org.apache.ibatis.reflection.factory.ObjectFactory and communicate it to the module and let Google Guice create it:

MyBatisModule module = new MyBatisModule() {

    @Override
    protected void initialize() {
        ...
        bindObjectFactoryType(com.acme.MyObjectFactory.class);
        ...
    }

};

Multiple Datasources

It often happens that users need to interact with multiple schemas in the same application, that means to have separate MyBatis configurations.

Fortunately, the Google Guice com.google.inject.PrivateModule comes to help us in a very simple and smart way, that will be shown in the following example.

Let's take in consideration, to simplify the example, we have only two datasources (but the same concept can be extended for an arbitrary data sources number) one for the contacts schema and another one for the companies schema. So, all it has to do is installing the org.mybatis.guice.MyBatisModule modules into the Google Guice com.google.inject.PrivateModule as shown below:

Injector injector = Guice.createInjector(
    new PrivateModule() {
        @Override
        protected void configure() {
            install(new MyBatisModule() {

                @Override
                protected void initialize() {
                    bindDataSourceProviderType(PooledDataSourceProvider.class);
                    bindTransactionFactoryType(JdbcTransactionFactory.class);
                    addMapperClass(ContactMapper.class);
                    addSimpleAlias(Contact.class);
                }

            });
            Names.bindProperties(this.binder(),
                getConnectionProperties("contacts"));
            // binds Mappers/DAOs here
            bind(ContactDao.class).to(ContactDaoImpl.class);
            ...

            // exposes Mappers/DAOs here
            expose(ContactDao.class);
            ...
        }
    }, new PrivateModule() {
        @Override
        protected void configure() {
            install(new MyBatisModule() {

                @Override
                protected void initialize() {
                    bindDataSourceProviderType(PooledDataSourceProvider.class);
                    bindTransactionFactoryType(JdbcTransactionFactory.class);
                }

            });
            Names.bindProperties(this.binder(),
                getConnectionProperties("trades"));
            // binds Mappers/DAOs here
            bind(CompanyDao.class).to(CompanyDaoImpl.class);
            ...

            // exposes Mappers/DAOs here
            expose(CompanyDao.class);
            ...
        }
    }
);

The example shows how to use the org.mybatis.guice.MyBatisModule to create two different MyBatis configurations in the same context. Feel free to implement the getConnectionProperties() method in the way you prefer! It could be, for example:

private final static Properties getConnectionProperties(String schema) {
    final Properties myBatisProperties = new Properties();

    myBatisProperties.setProperty("mybatis.environment.id", "test");
    myBatisProperties.setProperty("JDBC.driver",
        "org.apache.derby.jdbc.EmbeddedDriver");
    myBatisProperties.setProperty("JDBC.url",
        "jdbc:mysql://localhost:3306/" + schema);
    myBatisProperties.setProperty("JDBC.username", "mybatis-user");
    myBatisProperties.setProperty("JDBC.password", "changeme");
    myBatisProperties.setProperty("JDBC.autoCommit", "true");

    return myBatisProperties;
}

MyBatis XML Bootstrap

Users that want configure the MyBatis via the XML configuration, without loosing any single feature of the org.mybatis.guice.MyBatisModule, can create their Injector using the org.mybatis.guice.XMLMyBatisModule.

XMLMyBatisModule clients have just to instantiate it specifying

  1. the MyBatis XML configuration file, located in the classpath, by default the module will look for mybatis-config.xml in the root in the classpath;

  2. the optional MyBatis environmentId, defaults to the default attribute of <environments> element;

  3. the optional java.util.Properties to fill placeholders in the MyBatis XML configuration, empty by default.

A typical use case could be identified in the following code snippet:

Properties props = new Properties();
props.setProperty("JDBC.username", "mybatis-user");
props.setProperty("JDBC.password", "changeme");

Injector injector = Guice.createInjector(
    new XMLMyBatisModule() {

        @Override
        protected void initialize() {
            setEnvironmentId("test");
            setClassPathResource("my/path/to/mybatis-config.xml");
            addProperties(props);
        }

    },
    ...
);

Important Google Guice will inject dependencies, if required, in the TypeHandlers and Interceptors.