mybatis 拦截结果集返回CachedRowSetImpl对象

本文介绍Mybatis中ResultSetHandler接口的功能与默认实现,展示如何通过自定义拦截器和ResultHandler处理查询结果,以返回CachedRowSetImpl对象,适用于特定场景下的结果集处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Mybatis的ResultSetHandler接口是用来处理查询结果Statement的,默认实现是DefaultResultSetHandelr类

public interface ResultSetHandler {

  <E> List<E> handleResultSets(Statement stmt) throws SQLException;

  <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;

  void handleOutputParameters(CallableStatement cs) throws SQLException;

}

在执行select语句时,会创建DefaultresultSetHandler对象处理Statement,并且添加拦截器

// 代码位置 org.apache.ibatis.session.Configuration#newResultSetHandler

   public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler,
      ResultHandler resultHandler, BoundSql boundSql) {
    ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
    resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
    return resultSetHandler;
  }

所有可以自定义拦截器,拦截其中的handleResultSets方法,实现自定义的结果集处理


import com.sun.rowset.CachedRowSetImpl;
import org.apache.ibatis.executor.result.DefaultResultContext;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.plugin.*;

import java.lang.reflect.Field;
import java.sql.Statement;
import java.util.Arrays;
import java.util.Properties;

@Intercepts({@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})})
public class CachedRowSetIntercept implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Class<? extends Object> targetClass = invocation.getTarget().getClass();
        Field resultHandlerField = targetClass.getDeclaredField("resultHandler");
        resultHandlerField.setAccessible(true);
        Object resultHandler = resultHandlerField.get(invocation.getTarget());
        // 如果是需要返回特定的结果,做特定的处理
        if (resultHandler != null && resultHandler instanceof CachedRowSetHandler) {
            Statement arg = (Statement) invocation.getArgs()[0];
            CachedRowSetImpl cachedRowSet = new CachedRowSetImpl();
            cachedRowSet.populate(arg.getResultSet());
            DefaultResultContext resultContext = new DefaultResultContext();
            resultContext.nextResultObject(cachedRowSet);
//            保存结果为CachedRowSetImpl对象
            ((CachedRowSetHandler) resultHandler).handleResult(resultContext);
            return Arrays.asList(cachedRowSet);
        }
        // 走原有逻辑
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
    }
}

因为需要返回CachedRowSetImpl对象,所以不能走mybatis的自动映射成Bean的代码逻辑。

这时需要用到Mybatis的ResultHandler这个接口

package org.apache.ibatis.session;

/**
 * @author Clinton Begin
 */
public interface ResultHandler<T> {

  void handleResult(ResultContext<? extends T> resultContext);

}

并且需要用到SqlSessionTemplate来执行mapper中sql,传入ResultHandler接口的一个对象,用于保存自定义的结果集

  @Autowired
    SqlSessionTemplate sqlSessionTemplate;

    @GetMapping("/get")
    public Object find(@RequestParam(value = "cityName", required = true) String cityName) {
        CachedRowSetHandler cachedRowSetHandler = new CachedRowSetHandler();
        Map<String, Object> param = new HashMap<>();
        param.put("cityName", cityName);
        sqlSessionTemplate.select("org.spring.springboot.dao.CityDao.findByName",param, cachedRowSetHandler);
        try {
            CachedRowSetImpl result = cachedRowSetHandler.getResult();
            if(result.size()>0 && !result.isAfterLast() &&result.next()){
                return result.getString(1)+result.getString(2)+result.getString(3);
            }
        } catch (SQLException e) {
            e.printStackTrace();
            return e;
        }
        return cachedRowSetHandler.getResult().toString();
    }
public class CachedRowSetHandler implements ResultHandler {
    private CachedRowSetImpl cachedRowSet;
    @Override
    public void handleResult(ResultContext resultContext) {
        cachedRowSet = (CachedRowSetImpl) resultContext.getResultObject();
    }

    public CachedRowSetImpl getResult() {
        return this.cachedRowSet;
    }
}

最后,还需要将自定义的拦截器配置到mybatis中去,在mybatis-config.xml中添加配置(这里是叫plugin)

    <plugins>
        <plugin interceptor="org.spring.springboot.resultset.CachedRowSetIntercept"></plugin>
    </plugins>

 

mapper文件如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="org.spring.springboot.dao.CityDao">
	<resultMap id="BaseResultMap" type="org.spring.springboot.domain.City">
		<result column="id" property="id" />
		<result column="province_id" property="provinceId" />
		<result column="city_name" property="cityName" />
		<result column="description" property="description" />
	</resultMap>

	<parameterMap id="City" type="org.spring.springboot.domain.City"/>

	<sql id="Base_Column_List">
		id, province_id, city_name, description
	</sql>

	<select id="findByName" resultMap="BaseResultMap" >
		select
		<include refid="Base_Column_List" />
		from city
		where city_name = #{cityName}
	</select>

</mapper>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值