换包的风险-mybatis

项目使用的持久层框架是ibatis3,即mybatis,开源包是ibatis-core-3.0.jar和ibatis-sqlmap-3.0-beta-10.jar(当然使用的是其中一个,其中的加载顺序在此不加赘述,原因是两个包相似度很高)。

在做项目的时候,需要返回HashMap数据类型,将每一行的id作为key,其他数据封装成某个数据类型最为value,在这里需要使用ResultHandler,不过该包不支持Proxy动态代理调用方式,只能调用DefaultSqlSession中的如下方法select(String statement, Object parameter, ResultHandler handler)才能使用。这不利于项目代码的统一,使用起来也不是很方便。代码如下:

//出自mybatis-3.0.1.jar, org.apache.ibatis.binding.MapperMethod.java
public Object execute(Object[] args) throws SQLException {
    Object result;
    if (SqlCommandType.INSERT == type) {
      Object param = getParam(args);
      result = sqlSession.insert(commandName, param);
    } else if (SqlCommandType.UPDATE == type) {
      Object param = getParam(args);
      result = sqlSession.update(commandName, param);
    } else if (SqlCommandType.DELETE == type) {
      Object param = getParam(args);
      result = sqlSession.delete(commandName, param);
    } else if (SqlCommandType.SELECT == type) {

    //在这里没有判断是否使用ResultHandler接口作为参数的情况
    //而是判断返回类型是List,否则返回单行数据
      if (returnsList) {
        result = executeForList(args);
      } else {
        Object param = getParam(args);
        result = sqlSession.selectOne(commandName, param);
      }
    } else {
      throw new BindingException("Unkown execution method for: " + commandName);
    }
    return result;
  }
  
  
  //出自org.apache.ibatis.session.defaults.DefaultSqlSession.java
  //该调用方法可使用ResultHandler接口
  public void select(String statement, Object parameter, ResultHandler handler) {
    select(statement, parameter, RowBounds.DEFAULT, handler);
  }

 

在mybatis3.1.0之后,就支持了通过动态代理使用ResultHandler作为参数调用的方法,代码如下:

//出自mybatis-3.1.0.jar, org.apache.ibatis.binding.MapperMethod.java
public Object execute(Object[] args) {
    Object result = null;
    if (SqlCommandType.INSERT == type) {
      Object param = getParam(args);
      result = sqlSession.insert(commandName, param);
    } else if (SqlCommandType.UPDATE == type) {
      Object param = getParam(args);
      result = sqlSession.update(commandName, param);
    } else if (SqlCommandType.DELETE == type) {
      Object param = getParam(args);
      result = sqlSession.delete(commandName, param);
    } else if (SqlCommandType.SELECT == type) {

     //返回类型必须是void,并使用ResultHandler接口作为参数
      if (returnsVoid && resultHandlerIndex != null) {
        executeWithResultHandler(args);
      } else if (returnsMany) {
        result = executeForMany(args);
      } else if (returnsMap) {
        result = executeForMap(args);
      } else {
        Object param = getParam(args);
        result = sqlSession.selectOne(commandName, param);
      }
    } else {
      throw new BindingException("Unknown execution method for: " + commandName);
    }
    return result;
  }

对比两个包中的代码,有两种优化方式可以选择:

1.修改mybatis3.0源代码,模仿mybatis3.1;

2.更换包为mybatis3.1.0

当然第一种方式修改源代码较为复杂,因此我选择第二种方法。

更换包后,重新部署环境,遇到以下问题:

1.原来包中Environmet不是final类型,新包变为final类型,在我的项目中有个地方继承了Environment,所以这个地方需要找个变通的方法修改,在此不加赘述

2.发布后,执行分页查询,后台报错,经查,是新旧包中某些类略有修改,而其他与之关联的包(例如rapidframework-3.9.jar)没有更新所致。例如:

在rapidframework-3.9.jar中有如下代码,并给出我的修改:

//出自rapidframework-3.9.jar:cn.org.rapid_framework.ibatis3.plugin.OffsetLimitInterceptor.java
private MappedStatement copyFromMappedStatement(MappedStatement ms,SqlSource newSqlSource) {
		Builder builder = new MappedStatement.Builder(ms.getConfiguration(),ms.getId(),newSqlSource,ms.getSqlCommandType());
		
		builder.resource(ms.getResource());
		builder.fetchSize(ms.getFetchSize());
		builder.statementType(ms.getStatementType());
		builder.keyGenerator(ms.getKeyGenerator());
		
		/* 下面这句ms.getKeyProperty()报错,原因是新包修改了MappedStatement类中keyProperty的数据类型,
		`* 将String改为String[],相应的get方法由getKeyProperty()改为getKeyProperties()
		 * 因此,这里我是如下修改的,原因是在分页查询时,我跟踪此处的keyProperties为null,而其他查询并未使用此处
		 * String[] s = ms.getKeyProperties();
		 * if(s == null){
		 *	builder.keyProperty(null);
		 * }else{
		 *	builder.keyProperty(s[0]);
		 * }
		 */
		builder.keyProperty(ms.getKeyProperty());
		
		//setStatementTimeout()
		builder.timeout(ms.getTimeout());
		
		//setStatementResultMap()
		builder.parameterMap(ms.getParameterMap());
		
		//setStatementResultMap()
		builder.resultMaps(ms.getResultMaps());
		builder.resultSetType(ms.getResultSetType());
	    
		//setStatementCache()
		builder.cache(ms.getCache());
		builder.flushCacheRequired(ms.isFlushCacheRequired());
		builder.useCache(ms.isUseCache());
		
		return builder.build();
	}

以上是我遇到的两个问题,更换包后,还需要更多的测试才可以部署到生产环境,否则客户们会疯的,可见,新包有风险,更换需谨慎哈!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值