spring jdbc 之二

spring jdbcTemplate 提供了很多查询和更新功能,但是如果我们需要高层次的抽象spring还有个RDBMS其中包括了SqlQuery,MappingSqlQuery,SqlUpdate等
我们首先来看下一个简单的查询简单例子
public class BokkQuery extends MappingSqlQuery<VersionInfo>
{
    public BokkQuery(DataSource dataSource)
    {
        super(dataSource, "select * from t_soft_version t where t.id=?");
        //设置参数
        super.declareParameter(new SqlParameter("id", Types.INTEGER));
        compile();
    }
  
    @Override
    protected VersionInfo mapRow(ResultSet rs, int i) throws SQLException
    {
        VersionInfo versionInfo = new VersionInfo();
        versionInfo.setId(rs.getInt("id"));
        versionInfo.setVersion_name(rs.getString("version_name"));
        return versionInfo;
    }
}

public static void main(String[] args)
{
    DataSource dataSource = (DataSource) cxf.getBean("dataSource");
    BokkTest test = new BokkTest();
    test.listbook(dataSource);
}

public void listbook(DataSource dataSource)
    {
        BokkQuery bokkQuery = new BokkQuery(dataSource);
        List<VersionInfo> list = bokkQuery.execute(new Object[]{11111});
        for (VersionInfo versionInfo : list)
        {
            System.out.println("versionname:" + versionInfo.getVersion_name());
        }

     }


首先我们看下RdbmsOperation下其类的结构图:



下面我们从declareParameter入手分下一下该功能是如何实现的,其具体的实现在MappingQuery的基类RdbmsOperation的源码可以看到
RdbmsOperation源码如下:
public abstract class RdbmsOperation
    implements InitializingBean
{

    public void declareParameter(SqlParameter param)
        throws InvalidDataAccessApiUsageException
    {
        //声明参数只能在compile之前,否则声明是无效的,并会抛出异常
        if(isCompiled())
        {
            throw new InvalidDataAccessApiUsageException("Cannot add parameters once the query is compiled");
        } else
        {
            //把参数添加到一个LinkedList集合的属性中,供compile方法使用
            declaredParameters.add(param);
            return;
        }
    }

   //我们看到了compile
    public final void compile()
        throws InvalidDataAccessApiUsageException
    {
        if(!isCompiled())
        {
            if(getSql() == null)
                throw new InvalidDataAccessApiUsageException("Property 'sql' is required");
            try
            {
                //调用了afterPropertesSet方法
                jdbcTemplate.afterPropertiesSet();
            }
            catch(IllegalArgumentException ex)
            {
                throw new InvalidDataAccessApiUsageException(ex.getMessage());
            }
            //调用compileInternal完成具体的compile过程,并设置compiled标志位
            compileInternal();
            compiled = true;
            if(logger.isDebugEnabled())
                logger.debug((new StringBuilder("RdbmsOperation with SQL [")).append(getSql()).append("] compiled").toString());
        }
    }

    public void afterPropertiesSet()
    {
        compile();
    }
}

compileInternal方法在sqlOperation里完成,在compileInternal中生成一个PreparedStatementCreatorFactory作为Statement的工厂,这个工厂负责生成参数的Statement,其源码如下:

protected final void compileInternal()
    {
        preparedStatementFactory = new PreparedStatementCreatorFactory(getSql(), getDeclaredParameters());
        preparedStatementFactory.setResultSetType(getResultSetType());
        preparedStatementFactory.setUpdatableResults(isUpdatableResults());
        preparedStatementFactory.setReturnGeneratedKeys(isReturnGeneratedKeys());
        if(getGeneratedKeysColumnNames() != null)
            preparedStatementFactory.setGeneratedKeysColumnNames(getGeneratedKeysColumnNames());
        preparedStatementFactory.setNativeJdbcExtractor(getJdbcTemplate().getNativeJdbcExtractor());
        onCompileInternal();
    }


在完成compile之后,对MappingSqlQuery的准备工作就基本完成,在执行查询时,实际执行的是SqlQuery的executeByNameParam方法,这个方法需要完成的工作包括配置sql语句,配置数据记录对象转换RowMapper,然后使用JdbcTemplate来完成数据的查询,并启动数据记录到java数据对象的转换,其源码如下:

  public List executeByNamedParam(Map paramMap, Map context)
        throws DataAccessException
    {
        validateNamedParameters(paramMap);
        //需要执行sql语句
        org.springframework.jdbc.core.namedparam.ParsedSql parsedSql = getParsedSql();
        MapSqlParameterSource paramSource = new MapSqlParameterSource(paramMap);
        String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource);
        //配置好SQL语句需要的Paramters即rowMapper,这个Rowmapper完成数据记录对象的转换
        Object params[] = NamedParameterUtils.buildValueArray(parsedSql, paramSource, getDeclaredParameters());
        RowMapper rowMapper = new RowMapper(params, context);
        //转换成Rowmapper调用的是jdbcTemplate中的模板方法
        return getJdbcTemplate().query(newPreparedStatementCreator(sqlToUse, params), rowMapper);
    }

猜你喜欢

转载自liuwuhen.iteye.com/blog/1632973
今日推荐