返回介绍

8.2.2 Update 中的回调函数

发布于 2025-04-22 22:09:15 字数 5090 浏览 0 评论 0 收藏 0

PreparedStatementCallback 作为一个接口,其中只有一个函数 doInPreparedStatement,这个函数是用于调用通用方法 execute 的时候无法处理的一些个性化处理方法,在 update 中的函数实现:

public Integer doInPreparedStatement(PreparedStatement ps) throws SQLException {

  try {

   if (pss != null) {

   //设置 PreparedStatement 所需的全部参数。

   pss.setValues(ps);

  }

   int rows = ps.executeUpdate();

   if (logger.isDebugEnabled()) {

    logger.debug("SQL update affected " + rows + " rows");

  }

   return rows;

 }

  finally {

   if (pss instanceof ParameterDisposer) {

    ((ParameterDisposer) pss).cleanupParameters();

  }

 }

}

其中用于真正执行 SQL 的 ps.executeUpdate 没有太多需要讲解的,因为我们平时在直接使用 JDBC 方式进行调用的时候会经常使用此方法。但是,对于设置输入参数的函数 pss.setValues (ps),我们有必要去深入研究一下。在没有分析源码之前,我们至少可以知道其功能,不妨再回顾下 Spring 中使用 SQL 的执行过程,直接使用:

jdbcTemplate.update("insert into user(name,age,sex)values(?,?,?)",

new Object[] { user.getName(), user.getAge(),

user.getSex() }, new int[] { java.sql.Types.VARCHAR,

java.sql.Types.INTEGER, java.sql.Types.VARCHAR });

SQL 语句对应的参数,对应参数的类型清晰明了,这都归功于 Spring 为我们做了封装,而真正的 JDBC 调用其实非常繁琐,你需要这么做:

PreparedStatement updateSales = con.prepareStatement("insert into user(name,age,

sex)values(?,?,?)");

updateSales.setString(1, user.getName());

updateSales.setInt(2, user.getAge());

updateSales.setString(3, user.getSex());

那么看看 Spring 是如何做到封装上面的操作呢?

首先,所有的操作都是以 pss.setValues(ps) 为入口的。还记得我们之前的分析路程吗?这个 pss 所代表的当前类正是 ArgPreparedStatementSetter。其中的 setValues 如下:

public void setValues(PreparedStatement ps) throws SQLException {

  int parameterPosition = 1;

  if (this.args != null) {

  //遍历每个参数以作类型匹配及转换

   for (int i = 0; i < this.args.length; i++) {

    Object arg = this.args[i];

   //如果是集合类则需要进入集合类内部递归解析集合内部属性

    if (arg instanceof Collection && this.argTypes[i] != Types.ARRAY) {

     Collection entries = (Collection) arg;

     for (Iterator it = entries.iterator(); it.hasNext();) {

      Object entry = it.next();

      if (entry instanceof Object[]) {

       Object[] valueArray = ((Object[])entry);

       for (int k = 0; k < valueArray.length; k++) {

        Object argValue = valueArray[k];

        doSetValue(ps, parameterPosition, this.argTypes[i],

       argValue);

       parameterPosition++;

      }

      }else {

       doSetValue(ps, parameterPosition, this.argTypes[i], entry);

      parameterPosition++;

     }

    }

    }else {

    //解析当前属性

    doSetValue(ps, parameterPosition, this.argTypes[i], arg);

    parameterPosition++;

   }

  }

 }

}

对单个参数及类型的匹配处理:

protected void doSetValue(PreparedStatement ps, int parameterPosition, int argType, Object argValue)

throws SQLException {

  StatementCreatorUtils.setParameterValue(ps, parameterPosition, argType, argValue);

}

public static void setParameterValue(

PreparedStatement ps, int paramIndex, int sqlType, Object inValue)

throws SQLException {

 setParameterValueInternal(ps, paramIndex, sqlType, null, null, inValue);

}

private static void setParameterValueInternal(

PreparedStatement ps, int paramIndex, int sqlType, String typeName, Integer

scale, Object inValue)

throws SQLException {

  String typeNameToUse = typeName;

  int sqlTypeToUse = sqlType;

  Object inValueToUse = inValue;

  if (inValue instanceof SqlParameterValue) {

   SqlParameterValue parameterValue = (SqlParameterValue) inValue;

   if (logger.isDebugEnabled()) {

    logger.debug("Overriding type info with runtime info from SqlParameterValue:

    column index " + paramIndex +

    ", SQL type " + parameterValue.getSqlType() +

    ", Type name " + parameterValue.getTypeName());

  }

   if (parameterValue.getSqlType() != SqlTypeValue.TYPE_UNKNOWN) {

    sqlTypeToUse = parameterValue.getSqlType();

  }

   if (parameterValue.getTypeName() != null) {

    typeNameToUse = parameterValue.getTypeName();

  }

   inValueToUse = parameterValue.getValue();

 }

  if (logger.isTraceEnabled()) {

   logger.trace("Setting SQL statement parameter value: column index " +

   paramIndex +

   ", parameter value [" + inValueToUse +

   "], value class [" + (inValueToUse != null ? inValueToUse.

   getClass().getName() : "null") +

   "], SQL type " + (sqlTypeToUse == SqlTypeValue.TYPE_UNKNOWN ?

   "unknown" : Integer.toString(sqlTypeToUse)));

 }

  if (inValueToUse == null) {

   setNull(ps, paramIndex, sqlTypeToUse, typeNameToUse);

 }

  else {

   setValue(ps, paramIndex, sqlTypeToUse, typeNameToUse, scale, inValueToUse);

 }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。