无奈修改ibatis源码以支持外部DataSource数据源解决方案(已有其他更好的方案)

不知道楼下的同学自己亲手验证过没有,帖子也竟然被投为"新手帖"

按照楼下同学说的,原来可以通过外围构造一个TransactionManager通过setTxManger()方法赋值过去....从而根本不需要更改ibatis的源码了...这个方法确实比原来的好..

String resource = "sql-map-config.xml";               
        Reader reader = Resources.getResourceAsReader (resource);                
        SqlMapClientImpl sqlMap = (SqlMapClientImpl) SqlMapClientBuilder.buildSqlMapClient(reader);               
        TransactionConfig transactionConfig = new ExternalTransactionConfig();        Properties properties = new Properties();               
        properties.setProperty("SetAutoCommitAllowed", "false");               
        transactionConfig.setDataSource(getDataSource());               
        transactionConfig.setProperties(properties);               
        TransactionManager txManager = new TransactionManager(transactionConfig);               
                       
        sqlMap.getDelegate().setTxManager(txManager);    



今天验证这个方案发现: 
  transactionConfig.setProperties(properties);     
错误:The method setProperties(Properties) is undefined for the type TransactionConfig


以上方案修改如下:

 把transactionConfig.setProperties(properties); 更改为transactionConfig.initialize(properties);



题记:

    有时候在做项目的时候,Ds需要被其他应用监控,需要用到外部的DataSource,而不能用框架本身的DS..而修改IBATIS的XML配置文件也做不到,无奈今天只能更改源码了...

下面大概简单介绍下各种配置文件和源码.

ibatis的xml配置文件 
    类似很多dao框架一样, 这个配置有oscache配置,datasource数据库连接池配置,sqlMap映射文件配置,详细配置请看博客或者google吧,这里就不详述了..但重点说下datasource配置:ibatis2.3.0提供3类DS,分别为SIMPLE,DBCP,JNDI..配置方法大同小异.. 配置好后,这样在ibatis初始化的时候就会建立相应的ds和连接池了.

问题所在
 
   1,ibatis可以读取任意一个xml文件,但xml的格式是规定死的..如配置文件必须以 打头等等.

   2,xml配置可兼容jndi规范,但是有时候项目中并没有写成jndi,而是以另一种xml配置文件存在.

   3,项目中需要用到其他ds,不允许新创建.

解决方案 
   基于以上的状况,我没有找到更好的解决方案,所以只能更改源码,思路是ibatis不构建自己的ds对象,而是公用其他模块的ds对象,思路很明确,所以代码也好改,原ibatis配置文件不配置ds,外部ds对象作为参数传入ibatis..

具体方法 
  总共修改2个类,主要是改下参数和赋值了ds对象而已,也没有仔细研究过源码,有不对的地方还请海涵``

//修改SqlMapClientBuilder.java               
              
/** 新增方法,把外部的ds传进去**/              
              
 /**          
   * add ds parameter by cj.yangjun@gmail.com          
   * @param reader          
   * @param ds          
   * @param forceCommit          
   * @return          
   */              
  public static SqlMapClient buildSqlMapClient(Reader reader,DataSource ds,boolean forceCommit) {               
//    return new XmlSqlMapClientBuilder().buildSqlMap(reader);               
    return new SqlMapConfigParser().parse(reader,ds,forceCommit);               
  }               
              
              
//修改SqlMapConfigParser.java               
              
              
/**parser是一个NodeletParser 类,The NodeletParser is a callback based parser similar to SAX.           
         
vars是作者构建的Variables,这里有个疑问**/              
 public SqlMapClient parse(Reader reader) {               
    try {               
      if (vars.sqlMapConfigConv != null) {               
         System.out.println("null");               
        reader = vars.sqlMapConfigConv.convertXml(reader);               
      }               
              
      usingStreams = false;               
                     
      parser.parse(reader);               
                     
      return vars.client;               
    } catch (Exception e) {               
      throw new RuntimeException("Error occurred.  Cause: " + e, e);               
    }               
  }               
              
              
/**新增方法,把外围ds传进入,并且赋值**/              
              
 public SqlMapClient parse(Reader reader,DataSource ds,boolean forceCommit){               
    vars.dataSource=ds;               
      vars.errorCtx.setActivity("configuring the transaction manager");               
      String type = "jdbc";               
      type = vars.typeHandlerFactory.resolveAlias(type);               
              
      TransactionManager txManager = null;//ibatis的思路是要构造一个TransactionManager 对象               
      try {               
          vars.errorCtx.setMoreInfo("Check the transaction manager type or class.");               
      TransactionConfig config = (TransactionConfig) Resources.instantiate(type);//需要构造一个JDBC类型TransactionConfig我们的ds等部分信息去填充这个TransactionConfig,JDBC的其他属性由这个config初始化               
         config.setDataSource(vars.dataSource);               
          config.setMaximumConcurrentTransactions(vars.client.getDelegate().getMaxTransactions());               
          vars.errorCtx.setMoreInfo("Check the transactio nmanager properties or configuration.");               
              config.initialize(vars.txProps);               
          vars.errorCtx.setMoreInfo(null);               
          txManager = new TransactionManager(config);               
              txManager.setForceCommit(forceCommit);               
      } catch (Exception e) {               
        if (e instanceof SqlMapException) {               
          throw (SqlMapException) e;               
        } else {               
          throw new SqlMapException("Error initializing TransactionManager.  Could not instantiate TransactionConfig.  Cause: " + e, e);               
        }               
      }               
              
      vars.client.getDelegate().setTxManager(txManager);// 根据这个manager初始化一些事务控制的对象               
                   
    return parse(reader);//parser是一个NodeletParser ,The NodeletParser is a callback based parser similar to SAX. 读取其他内容并初始化...               
  }       


修改过,简单测试下,应该是可以用的..

疑问
在看的过程对有个地方有个疑问:
有如下结构关系:
public class SqlMapConfigParser extends BaseParser{

...

}

public abstract class BaseParser { 
  protected final Variables vars; 

   protected static class Variables {

          public ExtendedSqlMapClient client;
          public SqlMapExecutorDelegate delegate;
          public TypeHandlerFactory typeHandlerFactory;
          public DataSource dataSource;

         ......

   }

}

其中Variables 的注释如下:

/**
   * Variables the parser uses.  This "struct" like class is necessary because
   * anonymous inner classes do not have access to non-final member fields of the parent class.
   * This way, we can make the Variables instance final, and use all of its public fields as
   * variables for parsing state.
   */
我不明白作者精心设计这个"struct"的目的是什么呢?没看明白这里的
because
   * anonymous inner classes do not have access to non-final member fields of the parent class.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值