JeeSite mybatis 升级3.4.0 foreach问题

          由于为了能在批量插入之后获取到自增id,所以之前用的mybatis需要升级,批量返回的在3.3.1之后才开始支持。

          但是升级之后,会有一些问题,对于覆盖重写的类如Configuration等出现的错误,是缺少参数,new一个参数放进去就可以了。但是后来发现之前用的foreach报错了,

报错内容为:There is no getter for property named '__frch_item_0' in 'class xxxx。

         之前在网上找了找发现并不是应为mybatis的原因,mybatis3.4对foreach循环的支持没有发生变化。

        后来没办法,调试跟踪代码发现是jeeSite上重写的类中对于新版的mybatis的foreach参数处理出现的问题,具体如下:  

        SQLHelper.java

    @SuppressWarnings("unchecked")
    public static void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject) throws SQLException {
        ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        if (parameterMappings != null) {
            Configuration configuration = mappedStatement.getConfiguration();
            TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
            MetaObject metaObject = parameterObject == null ? null :
                    configuration.newMetaObject(parameterObject);
            for (int i = 0; i < parameterMappings.size(); i++) {
                ParameterMapping parameterMapping = parameterMappings.get(i);
                if (parameterMapping.getMode() != ParameterMode.OUT) {
                    Object value;
                    String propertyName = parameterMapping.getProperty();
                    PropertyTokenizer prop = new PropertyTokenizer(propertyName);
                    if (parameterObject == null) {
                        value = null;
                    } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                        value = parameterObject;
                    } else if (boundSql.hasAdditionalParameter(propertyName)) {// list类型foreach应该走到这,但是却到了else里面,是因为boundSql的additionalParameter是空的。
                        value = boundSql.getAdditionalParameter(propertyName);
                    } else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX) && boundSql.hasAdditionalParameter(prop.getName())) {
                        value = boundSql.getAdditionalParameter(prop.getName());
                        if (value != null) {
                            value = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length()));
                        }
                    } else {
                        value = metaObject == null ? null : metaObject.getValue(propertyName);
                    }
                    @SuppressWarnings("rawtypes")
					TypeHandler typeHandler = parameterMapping.getTypeHandler();
                    if (typeHandler == null) {
                        throw new ExecutorException("There was no TypeHandler found for parameter " + propertyName + " of statement " + mappedStatement.getId());
                    }
                    typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());
                }
            }
        }
    }
    list类型foreach应该走到这,但是却到了else里面,是因为boundSql的additionalParameter是空的。所以到上一级调用类中见additionalParameter加上就可以了。如下:
    
        SQLHelper-getCount中:

      

  public static int getCount(final String sql, final Connection connection,
    							final MappedStatement mappedStatement, final Object parameterObject,
    							final BoundSql boundSql, Log log) throws SQLException {
    	String dbName = Global.getConfig("jdbc.type");
		final String countSql;
		if("oracle".equals(dbName)){
			countSql = "select count(1) from (" + sql + ") tmp_count";
		}else{
			countSql = "select count(1) from (" + removeOrders(sql) + ") tmp_count";
//	        countSql = "select count(1) " + removeSelect(removeOrders(sql));
		}
        Connection conn = connection;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
        	if (log.isDebugEnabled()) {
                log.debug("COUNT SQL: " + StringUtils.replaceEach(countSql, new String[]{"\n","\t"}, new String[]{" "," "}));
            }
        	if (conn == null){
        		conn = mappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection();
            }
        	ps = conn.prepareStatement(countSql);
            BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql,
                    boundSql.getParameterMappings(), parameterObject);
            
          //解决MyBatis 分页foreach list item问题! 升级3.4.0后的问题 此部分为新增内容
			if (Reflections.getFieldValue(boundSql, "additionalParameters") != null) {
				@SuppressWarnings("unchecked")
				Map<String, Object> mo = (Map<String, Object>) Reflections.getFieldValue(boundSql, "additionalParameters");
				Reflections.setFieldValue(countBS, "additionalParameters", mo);
			}
            //升级3.4.0后的问题 此部分为新增内容 end

            //解决MyBatis 分页foreach 参数失效 start
			if (Reflections.getFieldValue(boundSql, "metaParameters") != null) {
				MetaObject mo = (MetaObject) Reflections.getFieldValue(boundSql, "metaParameters");
				Reflections.setFieldValue(countBS, "metaParameters", mo);
			}
			//解决MyBatis 分页foreach 参数失效 end 
            SQLHelper.setParameters(ps, mappedStatement, countBS, parameterObject);
            rs = ps.executeQuery();
            int count = 0;
            if (rs.next()) {
                count = rs.getInt(1);
            }
            return count;
        } finally {
            if (rs != null) {
                rs.close();
            }
            if (ps != null) {
            	ps.close();
            }
            if (conn != null) {
            	conn.close();
            }
        }
    }
       除此之外,还要在PaginationInterceptor.java中增加一部分处理如下:

@Override
    public Object intercept(Invocation invocation) throws Throwable {

        final MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        
//        //拦截需要分页的SQL
        if (mappedStatement.getId().matches(_SQL_PATTERN)) {
//        if (StringUtils.indexOfIgnoreCase(mappedStatement.getId(), _SQL_PATTERN) != -1) {
            Object parameter = invocation.getArgs()[1];
            BoundSql boundSql = mappedStatement.getBoundSql(parameter);
            Object parameterObject = boundSql.getParameterObject();

            //获取分页参数对象
            Page<Object> page = null;
            if (parameterObject != null) {
                page = convertParameter(parameterObject, page);
            }

            //如果设置了分页对象,则进行分页
            if (page != null && page.getPageSize() != -1) {

            	if (StringUtils.isBlank(boundSql.getSql())){
                    return null;
                }
                String originalSql = boundSql.getSql().trim();
            	
                //得到总记录数
                page.setCount(SQLHelper.getCount(originalSql, null, mappedStatement, parameterObject, boundSql, log));

                //分页查询 本地化对象 修改数据库注意修改实现
                String pageSql = SQLHelper.generatePageSql(originalSql, page, DIALECT);
//                if (log.isDebugEnabled()) {
//                    log.debug("PAGE SQL:" + StringUtils.replace(pageSql, "\n", ""));
//                }
                invocation.getArgs()[2] = new RowBounds(RowBounds.NO_ROW_OFFSET, RowBounds.NO_ROW_LIMIT);
                BoundSql newBoundSql = new BoundSql(mappedStatement.getConfiguration(), pageSql, boundSql.getParameterMappings(), boundSql.getParameterObject());
              //解决MyBatis 分页foreach list item问题!  升级3.4.0后的问题 此部分新增
    			if (Reflections.getFieldValue(boundSql, "additionalParameters") != null) {
    				@SuppressWarnings("unchecked")
    				Map<String, Object> mo = (Map<String, Object>) Reflections.getFieldValue(boundSql, "additionalParameters");
    				Reflections.setFieldValue(newBoundSql, "additionalParameters", mo);
    			} 
             //解决MyBatis 分页foreach list item问题!  升级3.4.0后的问题 此部分新增,end

             //解决MyBatis 分页foreach 参数失效 start
                if (Reflections.getFieldValue(boundSql, "metaParameters") != null) {
                    MetaObject mo = (MetaObject) Reflections.getFieldValue(boundSql, "metaParameters");
                    Reflections.setFieldValue(newBoundSql, "metaParameters", mo);
                }
                //解决MyBatis 分页foreach 参数失效 end
                MappedStatement newMs = copyFromMappedStatement(mappedStatement, new BoundSqlSqlSource(newBoundSql));

                invocation.getArgs()[0] = newMs;
            }
//        }
        return invocation.proceed();

}

注意:升级后的项目,activiti工作流将不能正常使用,原因是Mybatis版本过高与Activiti不再兼容,需要升级Activiti。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JeeSite是基于多个优秀的开源项目,高度整合封装而成的高效,高性能,强安全性的开源Java EE快速开发平台。 JeeSite本身是以Spring Framework为核心容器,Spring MVC为模型视图控制器,MyBatis为数据访问层, Apache Shiro为权限授权层,Ehcahe对常用数据进行缓存,Activit为工作流引擎。 JeeSite主要定位于企业信息化领域,已内置企业信息化系统的基础功能和高效的代码生成工具,包括:系统权限组件、数据权限组件、数据字典组件、核心工具组件、视图操作组件、工作流组件、代码生成等。前端界面风格采用了结构简单、性能优良、页面美观大气的Twitter Bootstrap页面展示框架。采用分层设计、双重验证、提交数据安全编码、密码加密、访问验证、数据权限验证。使用Maven做项目管理,提高项目的易开发性、扩展性。 JeeSite目前包括以下三大模块,系统管理(SYS)模块、内容管理(CMS)模块、在线办公(OA)模块、代码生成(GEN)模块。 系统管理模块 ,包括企业组织架构(用户管理、机构管理、区域管理)、菜单管理、角色权限管理、字典管理等功能; 内容管理模块 ,包括内容管理(文章、链接),栏目管理、站点管理、公共留言、文件管理、前端网站展示等功能; 在线办公模块 ,提供简单的请假流程实例。 JeeSite 提供了常用工具进行封装,包括日志工具、缓存工具、服务器端验证、数据字典、当前组织机构数据(用户、机构、区域)以及其它常用小工具等。另外还提供一个强大的在线 代码生成 工具,此工具提供简单的单表、一对多、树结构功能的生成,如果对外观要求不是很高,生成的功能就可以用了。如果你使用了JeeSite基础框架,就可以很高效的快速开发出,优秀的信息管理系统。 2.内置功能 1.用户管理:用户是系统操作者,该功能主要完成系统用户配置。 2.机构管理:配置系统组织机构(公司、部门、小组),树结构展现,可随意调整上下级。 3.区域管理:系统城市区域模型,如:国家、省市、地市、区县的维护。 4.菜单管理:配置系统菜单,操作权限,按钮权限标识等。 5.角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 6.字典管理:对系统中经常使用的一些较为固定的数据进行维护,如:是否、男女、类别、级别等。 7.操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 8.连接池监视:监视当期系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 9.工作流引擎:实现业务工单流转、在线流程设计器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值