Powerful persistence layer
           with
Google Guice & MyBatis

     GuiceCon, March 19th, 2011
               Simone Tripodi
          simonetripodi@apache.org
  http://people.apache.org/~simonetripodi
MyBatis?!?
It reminds Apache iBATIS!


Indeed, MyBatis is the Apache iBATIS fork!
● Fork happened on 2010;

● The whole original team moved the project on

Google Code;
● Apache iBATIS moved to Attic and no more

maintained;
● New extensions after left ASF.
The Guice integration early days...


● Announced as independent project on Google
Code on December 2009 with iBaGuice name;
● Only 2 folks behind it: Simone Tripodi & Marco

Speranza;
● Focused on providing a smart iBATIS bootstrap and

related component injection.
... and the merge with MyBatis


● Donated to MyBatis after the iBATIS fork;
● Community supported;

● Same objectives, better APIs;

● More 3
           rd
              parties integration:
  ● Apache Commons DBCP;

  ● Bone CP;

  ● C3P0;

  ● Built-in MyBatis DataSource.
MyBatis Confguration & Bootstrap


createInjector(new MyBatisModule() {

             @Override
             protected void initialize() {
                 environmentId("test");
                 bindDataSourceProviderType(PooledDataSourceProvider.class);
                 bindTransactionFactoryType(JdbcTransactionFactory.class);
                 addMapperClass(ContactMapper.class);
                 handleType(CustomType.class).with(CustomLongTypeHandler.class);
                 handleType(Address.class).with(AddressTypeHandler.class);
                 addInterceptorClass(CountUpdateInterceptor.class);
             }

       });
MyBatis XML Confguration
                        & Bootstrap


createInjector(new XMLMyBatisModule() {

             @Override
             protected void initialize() {
                 setEnvironmentId("test");
                 setClassPathResource("org/acme/mybatis-config.xml");
             }

       });
Require Mappers injection
public interface ContactMapper {

    void brokenAdd(Contact contact);

    void add(Contact contact);

    void update(Contact contact);

    void delete(Integer id);

    Contact getById(Integer id);

    List<Contact> selectAll();

}




@javax.inject.Singleton
public class ContactMapperClient {

    @javax.inject.Inject
    private ContactMapper contactMapper;

    public void setContactMapper(ContactMapper contactMapper) {
        this.contactMapper = contactMapper;
    }

}
rd
                        3 parties DataSource

createInjector(new XMLMyBatisModule() {

             @Override
             protected void initialize() {
                 // MyBatis built-in
                 bindDataSourceProviderType(UnpooledDataSourceProvider.class);
                 bindDataSourceProviderType(PooledDataSourceProvider.class);
                 bindDataSourceProviderType(JndiDataSourceProvider.class);

                 // c3p0
                 bindDataSourceProviderType(C3p0DataSourceProvider.class);

                 // apache commons-dbcp
                 bindDataSourceProviderType(BasicDataSourceProvider.class);
                 bindDataSourceProviderType(SharedPoolDataSourceProvider.class);
                 bindDataSourceProviderType(PerUserPoolDataSourceProvider.class);

                 // BoneCP
                 bindDataSourceProviderType(BoneCPProvider.class);
             }

       });
Issue: boring transactions!
public class FooDao {

    @Inject
    private SqlSessionManager sessionManager;

    public void setSessionManager(SqlSessionManager sessionManager) {
        this.sessionManager = sessionManager;
    }

    public void doFooBar() throws MyDaoException {
        this.sessionManager.startManagedSession(ExecutorType.BATCH,
TransactionIsolationLevel.READ_UNCOMMITTED);
        try {
            FooMapper fooMapper = this.sessionManager.getMapper(FooMapper.class);
            fooMapper.doFoo();
            BarMapper barMapper = this.sessionManager.getMapper(BarMapper.class);
            barMapper.doBar();
            this.sessionManager.commit();
        } catch (Throwable t) {
            this.sessionManager.rollback();
            throw new MyDaoException("Something went wrong", t);
        } finally {
            this.sessionManager.close();
    }

}
Solution: @Transactional

public class FooDao {

    @Inject
    private FooMapper fooMapper;

    @Inject
    private BarMapper barMapper;

    // let's assume setters here

    @Transactional(executorType = ExecutorType.BATCH,
        isolationLevel = TransactionIsolationLevel.READ_UNCOMMITTED,
        rethrowExceptionsAs = MyDaoException.class,
        exceptionMessage = "Something went wrong")
    public void doFooBar() {
        this.fooMapper.doFoo();
        this.barMapper.doBar();
    }

}
JDBC Helper



Small issue: remember JDBC URL patterns and driver
class names
● Create index/catalog? :(

● Create automatic index/catalog! :)
JDBCHelper in action

● Just a module that automatically injects JDBC.url and
JDBC.driver properties used by DataSource providers;
● JDBC.url is a template;

  ● Pattern contains variables in ${name|defaultValue} format;

  ● Patterns require other properties, i.e.:

     jdbc:mysql://${JDBC.host|localhost}:${JDBC.port|3306}/${JDBC.schema}

●   Sample?
createInjector(JdbcHelper.MySQL, ...);
References


MyBatis home page: http://mybatis.org/

Google-Guice integration module:
http://code.google.com/p/mybatis/downloads/list?can=3&q=Product%3DGuice


Google-Guice integration SVN:
http://mybatis.googlecode.com/svn/sub-projects/mybatis-guice/trunk/
G R A Z I E :)

Powerful persistence layer with Google Guice & MyBatis

  • 1.
    Powerful persistence layer with Google Guice & MyBatis GuiceCon, March 19th, 2011 Simone Tripodi simonetripodi@apache.org http://people.apache.org/~simonetripodi
  • 2.
  • 3.
    It reminds ApacheiBATIS! Indeed, MyBatis is the Apache iBATIS fork! ● Fork happened on 2010; ● The whole original team moved the project on Google Code; ● Apache iBATIS moved to Attic and no more maintained; ● New extensions after left ASF.
  • 5.
    The Guice integrationearly days... ● Announced as independent project on Google Code on December 2009 with iBaGuice name; ● Only 2 folks behind it: Simone Tripodi & Marco Speranza; ● Focused on providing a smart iBATIS bootstrap and related component injection.
  • 6.
    ... and themerge with MyBatis ● Donated to MyBatis after the iBATIS fork; ● Community supported; ● Same objectives, better APIs; ● More 3 rd parties integration: ● Apache Commons DBCP; ● Bone CP; ● C3P0; ● Built-in MyBatis DataSource.
  • 7.
    MyBatis Confguration &Bootstrap createInjector(new MyBatisModule() { @Override protected void initialize() { environmentId("test"); bindDataSourceProviderType(PooledDataSourceProvider.class); bindTransactionFactoryType(JdbcTransactionFactory.class); addMapperClass(ContactMapper.class); handleType(CustomType.class).with(CustomLongTypeHandler.class); handleType(Address.class).with(AddressTypeHandler.class); addInterceptorClass(CountUpdateInterceptor.class); } });
  • 8.
    MyBatis XML Confguration & Bootstrap createInjector(new XMLMyBatisModule() { @Override protected void initialize() { setEnvironmentId("test"); setClassPathResource("org/acme/mybatis-config.xml"); } });
  • 9.
    Require Mappers injection publicinterface ContactMapper { void brokenAdd(Contact contact); void add(Contact contact); void update(Contact contact); void delete(Integer id); Contact getById(Integer id); List<Contact> selectAll(); } @javax.inject.Singleton public class ContactMapperClient { @javax.inject.Inject private ContactMapper contactMapper; public void setContactMapper(ContactMapper contactMapper) { this.contactMapper = contactMapper; } }
  • 10.
    rd 3 parties DataSource createInjector(new XMLMyBatisModule() { @Override protected void initialize() { // MyBatis built-in bindDataSourceProviderType(UnpooledDataSourceProvider.class); bindDataSourceProviderType(PooledDataSourceProvider.class); bindDataSourceProviderType(JndiDataSourceProvider.class); // c3p0 bindDataSourceProviderType(C3p0DataSourceProvider.class); // apache commons-dbcp bindDataSourceProviderType(BasicDataSourceProvider.class); bindDataSourceProviderType(SharedPoolDataSourceProvider.class); bindDataSourceProviderType(PerUserPoolDataSourceProvider.class); // BoneCP bindDataSourceProviderType(BoneCPProvider.class); } });
  • 11.
    Issue: boring transactions! publicclass FooDao { @Inject private SqlSessionManager sessionManager; public void setSessionManager(SqlSessionManager sessionManager) { this.sessionManager = sessionManager; } public void doFooBar() throws MyDaoException { this.sessionManager.startManagedSession(ExecutorType.BATCH, TransactionIsolationLevel.READ_UNCOMMITTED); try { FooMapper fooMapper = this.sessionManager.getMapper(FooMapper.class); fooMapper.doFoo(); BarMapper barMapper = this.sessionManager.getMapper(BarMapper.class); barMapper.doBar(); this.sessionManager.commit(); } catch (Throwable t) { this.sessionManager.rollback(); throw new MyDaoException("Something went wrong", t); } finally { this.sessionManager.close(); } }
  • 12.
    Solution: @Transactional public classFooDao { @Inject private FooMapper fooMapper; @Inject private BarMapper barMapper; // let's assume setters here @Transactional(executorType = ExecutorType.BATCH, isolationLevel = TransactionIsolationLevel.READ_UNCOMMITTED, rethrowExceptionsAs = MyDaoException.class, exceptionMessage = "Something went wrong") public void doFooBar() { this.fooMapper.doFoo(); this.barMapper.doBar(); } }
  • 13.
    JDBC Helper Small issue:remember JDBC URL patterns and driver class names ● Create index/catalog? :( ● Create automatic index/catalog! :)
  • 14.
    JDBCHelper in action ●Just a module that automatically injects JDBC.url and JDBC.driver properties used by DataSource providers; ● JDBC.url is a template; ● Pattern contains variables in ${name|defaultValue} format; ● Patterns require other properties, i.e.: jdbc:mysql://${JDBC.host|localhost}:${JDBC.port|3306}/${JDBC.schema} ● Sample? createInjector(JdbcHelper.MySQL, ...);
  • 15.
    References MyBatis home page:http://mybatis.org/ Google-Guice integration module: http://code.google.com/p/mybatis/downloads/list?can=3&q=Product%3DGuice Google-Guice integration SVN: http://mybatis.googlecode.com/svn/sub-projects/mybatis-guice/trunk/
  • 16.
    G R AZ I E :)