日期:2014-05-16  浏览次数:20408 次

修改MyBatis源代码以支持数据库分页,自动总行数统计及Object[]数据结果,之二(修改源代码)

?

1、 修改DTD,增加Environment 节点属性配置:

?

<!ELEMENT environment (transactionManager,dataSource)>

<!ATTLIST environment

id CDATA #REQUIRED

>

为:

<!ELEMENT environment (transactionManager,dataSource)>

<!ATTLIST environment

id CDATA #REQUIRED

dialect CDATA #REQUIRED

>

?2、添加支持类:

(1)分页结果列表

(2)dialect基本类及其各种数据库实现,此处参考了Hibernate的dialect和网友文章,具体的dialect及其实现自己谷歌或百度或查看Hibernate源代码。

3、修改org.apache.ibatis.builder.xml.XMLConfigBuilder

183 行,private void environmentsElement(XNode context) throws Exception 方法:

注意加深背景颜色:

?

  private void environmentsElement(XNode context) throws Exception {

    if (context != null) {

      if (environment == null) {

        environment = context.getStringAttribute("default");

      }

      for (XNode child : context.getChildren()) {

        String id = child.getStringAttribute("id");

        String dialect=child.getStringAttribute("dialect");

        if (isSpecifiedEnvironment(id)) {

          TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));

          DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));

          Environment.Builder environmentBuilder = new Environment.Builder(id,dialect)

              .transactionFactory(txFactory)

              .dataSource(dsFactory.getDataSource());

          configuration.setEnvironment(environmentBuilder.build());

        }

      }

    }

  }

?

4、同时修改org.apache.ibatis.mapping. Environment.Builder 构造器,能见XML配置中的dialect,传入:

private String dialectClass;

 

public Builder(String id, String dialect) {

this.id = id;

this.dialectClass = dialect;

}


并修改org.apache.ibatis.mapping.Environment:

private final Dialect dialect;

 

public Environment(

String id,

Dialect dialect,

TransactionFactory transactionFactory,

DataSource dataSource) {

if (id == null) {

throw new IllegalArgumentException("Parameter 'id' must not be null");

}

if (transactionFactory == null) {

throw new IllegalArgumentException(

"Parameter 'transactionFactory' must not be null");

}

this.id = id;

if (dataSource == null) {

throw new IllegalArgumentException("Parameter 'dataSource' must not be null");

}

this.transactionFactory = transactionFactory;

this.dataSource = dataSource;

this.dialect = dialect;

}

同时修改org.apache.ibatis.mapping. Environment.Builder,build()方法,根据配置动态创建Dialect实例,并传入Environment

 

public Environment build() {

Dialect dialect = null;

if (dialectClass == null || "".equals(dialectClass)) {

throw new NullPointerException("environment dialect can't empty!");

} else {

try {

dialect = (Dialect) Class.forName(dialectClass).newInstance();

} catch (InstantiationException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

return new Environment(this.id, dialect, this.transactionFactory, this.dataSource);

}

 

并创建,以便外部能调用。

public Dialect getDialect() {

return dialect;

}

5、最终将Dialect实例传入给org.apache.ibatis.executor.statement.RoutingStatementHandler,在RoutingStatementHandler中操作分页和自动统计:

(1)、修改StatementHandler接口,使其所有的实现暴露RowBounds,能够调用 

(2)、修改BoundSql,添加: public void setSql(

String sql) {

this.sql = sql;

}

使其能将修改后的分页语句重新设置放入。

(3)修改RoutingStatementHandler,主要修改增加dialect = ms.getConfiguration().getEnvironment().getDialect();能够初始化方言。

   修改 public Statement prepare(Connection connection) throws SQLException 

public <T> List<T> query(Statement statement, ResultHandler resultHandler)

添加

private int getCount() throws SQLException {

方法,如下:

package org.apache.ibatis.executor.statement;

 

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sq