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。

  

 

posted @   猪脚踏浪  阅读(942)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示