• SpringJDBC解析3-回调函数(update为例)


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

    protected int update(final PreparedStatementCreator psc, final PreparedStatementSetter pss)  
            throws DataAccessException {  
      
        logger.debug("Executing prepared SQL update");  
        return execute(psc, new PreparedStatementCallback<Integer>() {  
            public Integer doInPreparedStatement(PreparedStatement ps) throws SQLException {  
                try {  
                    if (pss != null) {  
                        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并没有太多需要讲的,但是,对于设置输入参数的函数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所代表的正式ArgumentTypePreparedStatementSetter。其中的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 (Object entry : entries) {  
                        if (entry instanceof Object[]) {  
                            Object[] valueArray = ((Object[]) entry);  
                            for (Object argValue : valueArray) {  
                                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++;  
                }  
            }  
        }  
    }

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

    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;  
      
        // override type info?  
        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);  
        }  
    }  

  • 相关阅读:
    基于docker的MongoDB复制(副本集)
    (已解决)ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib
    【洛谷3530】[POI2012] FES-Festival(差分约束+Tarjan)
    【洛谷4765】[CERC2014] The Imp(贪心+DP)
    【洛谷7093】[CERC2014] Can't stop playing(搜索)
    【CF755G】PolandBall and Many Other Balls(倍增FFT)
    【洛谷3896】[湖南集训] Clever Rabbit(搜索)
    【洛谷7215】[JOISC2020] 首都(点分治+BFS)
    【BZOJ4173】数学(欧拉函数)
    【洛谷5748】集合划分计数(多项式exp)
  • 原文地址:https://www.cnblogs.com/wade-luffy/p/6079994.html
Copyright © 2020-2023  润新知