Powerful persistence layer with Google Guice & MyBatis

16
Powerful persistence layer with Google Guice & MyBatis GuiceCon, March 19th, 2011 Simone Tripodi [email protected] http://people.apache.org/~simonetripodi

description

 

Transcript of Powerful persistence layer with Google Guice & MyBatis

Page 1: Powerful persistence layer with Google Guice & MyBatis

Powerful persistence layerwith

Google Guice & MyBatis

GuiceCon, March 19th, 2011

Simone [email protected]

http://people.apache.org/~simonetripodi

Page 2: Powerful persistence layer with Google Guice & MyBatis

MyBatis?!?

Page 3: Powerful persistence layer with Google Guice & 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.

Page 4: Powerful persistence layer with Google Guice & MyBatis
Page 5: Powerful persistence layer with Google Guice & MyBatis

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.

Page 6: Powerful persistence layer with Google Guice & MyBatis

... and the merge with MyBatis

● Donated to MyBatis after the iBATIS fork;● Community supported;● Same objectives, better APIs;● More 3rd parties integration:

● Apache Commons DBCP;● Bone CP;● C3P0;● Built-in MyBatis DataSource.

Page 7: Powerful persistence layer with Google Guice & MyBatis

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); }

});

Page 8: Powerful persistence layer with Google Guice & MyBatis

MyBatis XML Confguration& Bootstrap

createInjector(new XMLMyBatisModule() {

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

});

Page 9: Powerful persistence layer with Google Guice & MyBatis

Require Mappers injectionpublic 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.Singletonpublic class ContactMapperClient {

@javax.inject.Inject private ContactMapper contactMapper;

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

}

Page 10: Powerful persistence layer with Google Guice & MyBatis

3rd 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); }

});

Page 11: Powerful persistence layer with Google Guice & MyBatis

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(); }

}

Page 12: Powerful persistence layer with Google Guice & MyBatis

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(); }

}

Page 13: Powerful persistence layer with Google Guice & MyBatis

JDBC Helper

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

Page 14: Powerful persistence layer with Google Guice & MyBatis

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, ...);

Page 15: Powerful persistence layer with Google Guice & MyBatis

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/

Page 16: Powerful persistence layer with Google Guice & MyBatis

G R A Z I E :)