MyBatis框架的使用及源码分析(十二) ParameterHandler
在StatementHandler使用prepare()方法后,接下来就是使用ParameterHandler来设置参数,让我们看看它的定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | package org.apache.ibatis.executor.parameter; import java.sql.PreparedStatement; import java.sql.SQLException; /** * A parameter handler sets the parameters of the {@code PreparedStatement} * * @author Clinton Begin */ public interface ParameterHandler { Object getParameterObject(); void setParameters(PreparedStatement ps) throws SQLException; } |
getParameterObject()是获取参数的,而setParameters()是设置参数的,相当于对一条sql所有的参数都执行ps.setXXX(value);
DefaultParameterHandler是它的实现类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | package org.apache.ibatis.scripting.defaults; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; import org.apache.ibatis.executor.ErrorContext; import org.apache.ibatis.executor.parameter.ParameterHandler; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.ParameterMapping; import org.apache.ibatis.mapping.ParameterMode; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.TypeException; import org.apache.ibatis.type.TypeHandler; import org.apache.ibatis.type.TypeHandlerRegistry; /** * @author Clinton Begin * @author Eduardo Macarron */ public class DefaultParameterHandler implements ParameterHandler { private final TypeHandlerRegistry typeHandlerRegistry; private final MappedStatement mappedStatement; private final Object parameterObject; //所有的参数值 private BoundSql boundSql; private Configuration configuration; public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) { this .mappedStatement = mappedStatement; this .configuration = mappedStatement.getConfiguration(); this .typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry(); this .parameterObject = parameterObject; this .boundSql = boundSql; } @Override public Object getParameterObject() { return parameterObject; } @Override public void setParameters(PreparedStatement ps) { ErrorContext.instance().activity( "setting parameters" ).object(mappedStatement.getParameterMap().getId()); //获取所有参数,ParameterMapping是java类型和jdbc类型的对应关系 List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); if (parameterMappings != null ) { for ( int i = 0 ; i < parameterMappings.size(); i++) { ParameterMapping parameterMapping = parameterMappings.get(i); if (parameterMapping.getMode() != ParameterMode.OUT) { //参数值 Object value; //获取参数名称 String propertyName = parameterMapping.getProperty(); if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params //获取参数值 value = boundSql.getAdditionalParameter(propertyName); } else if (parameterObject == null ) { value = null ; } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) //如果是单个值则直接赋值 value = parameterObject; } else { MetaObject metaObject = configuration.newMetaObject(parameterObject); value = metaObject.getValue(propertyName); } //获取参数值对应的jdbc类型 TypeHandler typeHandler = parameterMapping.getTypeHandler(); JdbcType jdbcType = parameterMapping.getJdbcType(); if (value == null && jdbcType == null ) { jdbcType = configuration.getJdbcTypeForNull(); } try { //设置参数值和jdbc类型的对应关系 typeHandler.setParameter(ps, i + 1 , value, jdbcType); } catch (TypeException e) { throw new TypeException( "Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e); } catch (SQLException e) { throw new TypeException( "Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e); } } } } } } |
getParameterObject是获取参数,这个参数值就是你传递进来的值,可能是个实体、map或单个基本类型数据。
重点看setParameters(),首先它读取了ParameterObject参数对象,然后用typeHandler对参数进行设置,而typeHandler里面需要对jdbcType和javaType进行处理,然后就设置参数了。也很好理解。所以当我们使用TypeHandler的时候完全可以控制如何设置SQL参数。设置参数,其实就是你在sql语句中配置的java对象和jdbc类型对应的关系,例如#{id,jdbcType=INTEGER},id默认类型是javaType=class java.lang.Integer。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端