Mybatis源码分析之参数映射及处理ParameterHandler

太过爱你忘了你带给我的痛 2022-07-15 12:53 357阅读 0赞

ParameterHandler是用来设置参数规则的,当StatementHandler调用prepare方法之后,接下来就是调用它来进行设置参数。

ParameterHandler接口:

  1. public interface ParameterHandler {
  2. Object getParameterObject();
  3. void setParameters(PreparedStatement ps)
  4. throws SQLException;
  5. }

getParameterObject是用来获取参数的,setParameters(PreparedStatement ps)是用来设置参数的,相当于对sql中所有的参数都执行ps.setXXX(value);

ParameterHandler的默认实现类是DefaultParameterHandler,其实现了接口中定义的两个方法。

getParameterObject是获取参数,这个参数值就是你传递进来的值,可能是个实体、map或单个基本类型数据。

  1. @Override
  2. public Object getParameterObject() {
  3. return parameterObject;
  4. }

设置参数,其实就是你在sql语句中配置的java对象和jdbc类型对应的关系#{id,jdbcType=INTEGER},id默认类型是javaType=class java.lang.Integer。

  1. //设置参数
  2. @Override
  3. public void setParameters(PreparedStatement ps) {
  4. ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
  5. //获取所有参数,ParameterMapping是java类型和jdbc类型的对应关系
  6. List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
  7. if (parameterMappings != null) {
  8. for (int i = 0; i < parameterMappings.size(); i++) {
  9. ParameterMapping parameterMapping = parameterMappings.get(i);
  10. if (parameterMapping.getMode() != ParameterMode.OUT) {
  11. //参数值
  12. Object value;
  13. //获取参数名称
  14. String propertyName = parameterMapping.getProperty();
  15. if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
  16. //获取参数值
  17. value = boundSql.getAdditionalParameter(propertyName);
  18. } else if (parameterObject == null) {
  19. value = null;
  20. } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
  21. //如果是单个值则直接赋值
  22. value = parameterObject;
  23. } else {
  24. MetaObject metaObject = configuration.newMetaObject(parameterObject);
  25. value = metaObject.getValue(propertyName);
  26. }
  27. //获取参数值对应的jdbc类型
  28. TypeHandler typeHandler = parameterMapping.getTypeHandler();
  29. JdbcType jdbcType = parameterMapping.getJdbcType();
  30. if (value == null && jdbcType == null) {
  31. jdbcType = configuration.getJdbcTypeForNull();
  32. }
  33. try {
  34. //设置参数值和jdbc类型的对应关系
  35. typeHandler.setParameter(ps, i + 1, value, jdbcType);
  36. } catch (TypeException e) {
  37. throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
  38. } catch (SQLException e) {
  39. throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
  40. }
  41. }
  42. }
  43. }
  44. }

这样就设置了一个参数值对应的jdbcType了

完整的DefaultParameterHandler源码如下:

  1. /**
  2. * @author Clinton Begin
  3. * @author Eduardo Macarron
  4. */
  5. public class DefaultParameterHandler implements ParameterHandler {
  6. private final TypeHandlerRegistry typeHandlerRegistry;
  7. private final MappedStatement mappedStatement;
  8. //所有的参数值
  9. private final Object parameterObject;
  10. private BoundSql boundSql;
  11. private Configuration configuration;
  12. public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
  13. this.mappedStatement = mappedStatement;
  14. this.configuration = mappedStatement.getConfiguration();
  15. this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
  16. this.parameterObject = parameterObject;
  17. this.boundSql = boundSql;
  18. }
  19. @Override
  20. public Object getParameterObject() {
  21. return parameterObject;
  22. }
  23. //设置参数
  24. @Override
  25. public void setParameters(PreparedStatement ps) {
  26. ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
  27. //获取所有参数,ParameterMapping是java类型和jdbc类型的对应关系
  28. List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
  29. if (parameterMappings != null) {
  30. for (int i = 0; i < parameterMappings.size(); i++) {
  31. ParameterMapping parameterMapping = parameterMappings.get(i);
  32. if (parameterMapping.getMode() != ParameterMode.OUT) {
  33. //参数值
  34. Object value;
  35. //获取参数名称
  36. String propertyName = parameterMapping.getProperty();
  37. if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
  38. //获取参数值
  39. value = boundSql.getAdditionalParameter(propertyName);
  40. } else if (parameterObject == null) {
  41. value = null;
  42. } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
  43. //如果是单个值则直接赋值
  44. value = parameterObject;
  45. } else {
  46. MetaObject metaObject = configuration.newMetaObject(parameterObject);
  47. value = metaObject.getValue(propertyName);
  48. }
  49. //获取参数值对应的jdbc类型
  50. TypeHandler typeHandler = parameterMapping.getTypeHandler();
  51. JdbcType jdbcType = parameterMapping.getJdbcType();
  52. if (value == null && jdbcType == null) {
  53. jdbcType = configuration.getJdbcTypeForNull();
  54. }
  55. try {
  56. //设置参数值和jdbc类型的对应关系
  57. typeHandler.setParameter(ps, i + 1, value, jdbcType);
  58. } catch (TypeException e) {
  59. throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
  60. } catch (SQLException e) {
  61. throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
  62. }
  63. }
  64. }
  65. }
  66. }
  67. }

发表评论

表情:
评论列表 (有 0 条评论,357人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Mybatis分析-Executor

      mybatis的源代码相对于spring的来说简单了很多,对于初学者,可以先了解了mybatis的源码后再去了解spring的源码,本文主要来分析下Executor的内容