要接入mybatis需要考虑以下几个方法的问题:
此项目是否还会引用hibernate(hibernate用的实在太广了没法忽视)?
与hibernate的事务如何共存?
与hibernate的配置如何统一(谁也不想一个项目配置多个数据库地址吧)?
SqlSessionFactory与SqlSession如何构建?SqlSession什么时候要释放?SqlSessionFactory需要释放吗?
mybatis模块会有默认的配置信息,但具体项目配置信息如何个性化?
带着这些问题,我们来探讨一下tapestry-mybatis模块的实现与配置.可以在oschina的第三方库中找到并下载http://maven.oschina.net/content/repositories/thirdparty/cn/rjzjh/tapestry-mybatis/
如何用maven可以加入库
<repository>
<id>oschina-third</id>
<url>http://maven.oschina.net/content/repositories/thirdparty/</url>
</repository>
并配置jar包,它附有源码:
<dependency>
<groupId>cn.rjzjh</groupId>
<artifactId>tapestry-mybatis</artifactId>
<version>1.0.4</version>
</dependency>
下面将对上面提及的5个问题看看tapestry-mybatis如何解决.
此项目是否还会引用hibernate(hibernate用的实在太广了没法忽视)?
项目可以通过配置常量 configuration.override(MybatisSymbols.HAS_HIBERNATE, true);来指示模块该项目存有hibernate.
与hibernate的事务如何共存?
该模块通过@CommitMybatis 指示方式提交mybatis事务,需要提交,如果存在hibernate,则通过hibernate的@CommitAfter注解不但会提交hibernate的事务也会同时提交mybatis的事务,它通过方法拦截,跟spring的AOP类似完成事务的提交,当出现运行时异常时将回自动回滚事务.mybatis的事务提交是发生在hibernate的事务提交之后.tapestry-hibernate模块的事务提交的原理与此相同,也就是说在调用方法正常执行完成后通过拦截方法先提交hibernate事务再提交mybatis事务,如果调用方法出现运行时异常时,会先回滚hibernate事务,再回滚mybatis事务.具体实现见类 cn.rjzjh.tapestry.mybatis.services.CommitMybatisWorker
与hibernate的配置如何统一(谁也不想一个项目配置多个数据库地址吧)?
这个需要各项目去个性化定制,但是mybatis模块为这种个性化定性提供了入口.,如示:
需要在项目的AppMoudle.java中增加配置,把hibernateSessionSource传给配置类:
public static void contributeIMybatisSessionSource( OrderedConfiguration<MybatisConfigurer> config,HibernateSessionSource hibernateSessionSource) { config.add("hib", new MybatisConfigurerFormHb(hibernateSessionSource)); }
在配置文件类中做如下配置
public class MybatisConfigurerFormHb implements MybatisConfigurer { private final HibernateSessionSource hibernateSessionSource; public MybatisConfigurerFormHb(HibernateSessionSource hibernateSessionSource) { this.hibernateSessionSource = hibernateSessionSource; } @Override public void configure(Configuration configuration) { C3P0ConnectionProvider cp = (C3P0ConnectionProvider) ((SessionFactoryImplementor) hibernateSessionSource .getSessionFactory()).getConnectionProvider(); DataSource dataSource = cp.unwrap(DataSource.class); TransactionFactory transactionFactory = new JdbcTransactionFactory(); Environment environment = new Environment("development", transactionFactory, dataSource); configuration.setEnvironment(environment); } }
就能完成mybatis与hibernate共用一个数据源,这个项目是在hibernate用了c3p0连接池的情况下适用.其它情况可依照此路径完成配置.
4. SqlSessionFactory与SqlSession如何构建?SqlSession什么时候要释放?SqlSessionFactory需要释放吗?
SqlSessionFactory通过IMybatisSessionSource服务来获得, IMybatisSessionSource是单类的,所以在项目中只存在唯一的一个SqlSessionFactory实例,它的关闭我原来打算在IMybatisSessionSource服务销毁时完成的,但是我发现 SqlSessionFactory没有关闭的方法,暂且遗留,如果有懂的同学可以给我点提醒,谢谢.但是实际上IMybatisSessionSource服务实例是不会销毁的,除非把服务器停了,服务器都停了SqlSessionFactory还用得了销毁吗?这样想想销毁也没必要的,看下面欲实现的代码,它在cn.rjzjh.tapestry.mybatis.services.MybatisSessionSourceImpl类中:
@PostInjection public void listenForShutdown(RegistryShutdownHub hub) { hub.addRegistryShutdownListener(new Runnable() { @Override public void run() { // sqlSessionFactory. 关闭sqlSessionFactory,但没有对应的方法 } }); }
SqlSession的创建是在每一个需要SqlSession服务的请求线程中自动创建的,代码如下:
@Scope(ScopeConstants.PERTHREAD) public static SqlSession buildSqlSession( SqlSessionFactory SqlSessionFactory, PerthreadManager perthreadManager) { final SqlSession retobj = SqlSessionFactory.openSession(); perthreadManager.addThreadCleanupCallback(new Runnable() { @Override public void run() { retobj.close(); // System.out.println("关闭session"); } }); return retobj; }
它也会在请求线程被销毁时通过回调线程销毁SqlSession实例.
5. mybatis模块会有默认的配置信息,但具体项目配置信息如何个性化?
mybatis不像hibernate那样有默认的配置为 classpath下的hibernate.cfg.xml文件,所以mybatis模块提供了一个默认的配置文件为classpath下的mybatis.xml文件,如果项目中与此文件名不一致,可以通过配置 值来实现:
configuration.override(MybatisSymbols.CONFIG_FILE_PATH, "aaaaa.xml");
如果有些配置在xml文件中不方便写可以通过编码的方式来配置mybatis,可以参考第3点.
具体使用示便可以参考 tams项目.