spring jdbc 之一

使用过jdbc的我们都知道spring jdbc ,首先我们看下JdbcTemplate 中的execute
在exceute的实现中看到了数据库进行操作的基本过程,比如需要获得数据库Connection,根据应用对数据库操作需要创建数据库的statement,对数据库操作进行回调,处理数据库异常
  最后把数据库的连接关闭,等等,这里展示了使用JDBC完成数据库操作的完整过程,只是在spring中,对这些较为普通的JDBC使用,JdbcTemplate进行了一个封装而已。
     public void execute(final String sql)
        throws DataAccessException
    {
   
        class _cls1ExecuteStatementCallback
            implements StatementCallback, SqlProvider
        {

            public Object doInStatement(Statement stmt)
                throws SQLException
            {
                stmt.execute(sql);
                return null;
            }

            public String getSql()
            {
                return sql;
            }

            final JdbcTemplate this$0;
            private final String val$sql;

            _cls1ExecuteStatementCallback()
            {
                this$0 = JdbcTemplate.this;
                sql = s;
                super();
            }
        }

        execute(((StatementCallback) (new _cls1ExecuteStatementCallback())));
    }


public Object execute(StatementCallback action)
        throws DataAccessException
    {
        Connection con;
        Statement stmt;
        Assert.notNull(action, "Callback object must not be null");
        con = DataSourceUtils.getConnection(getDataSource());
        stmt = null;
        Object obj;
        try
        {
            Connection conToUse = con;
            if(nativeJdbcExtractor != null && nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements())
                conToUse = nativeJdbcExtractor.getNativeConnection(con);
            stmt = conToUse.createStatement();
            applyStatementSettings(stmt);
            Statement stmtToUse = stmt;
            if(nativeJdbcExtractor != null)
                stmtToUse = nativeJdbcExtractor.getNativeStatement(stmt);
            //通过回调函数等到结果
            Object result = action.doInStatement(stmtToUse);
            handleWarnings(stmt);
            obj = result;
        }
        catch(SQLException ex)
        {
            JdbcUtils.closeStatement(stmt);
            stmt = null;
            DataSourceUtils.releaseConnection(con, getDataSource());
            con = null;
            throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex);
        }
        JdbcUtils.closeStatement(stmt);
        DataSourceUtils.releaseConnection(con, getDataSource());
        return obj;
        Exception exception;
        exception;
        JdbcUtils.closeStatement(stmt);
        DataSourceUtils.releaseConnection(con, getDataSource());
        throw exception;
    }

jdbc的基本原理其中的execute方法,我们在看下jdbcTemplate中的query方法
    public Object query(PreparedStatementCreator psc, final PreparedStatementSetter pss, final ResultSetExtractor rse)
        throws DataAccessException
    {
        return execute(psc, new PreparedStatementCallback() {
            public Object doInPreparedStatement(PreparedStatement ps)
                throws SQLException
            {
                ResultSet rs = null;
                Object obj;
                if(pss != null)
                   pss.setValues(ps);
                rs = ps.executeQuery();
                ResultSet rsToUse = rs;
                if(nativeJdbcExtractor != null)
                    rsToUse = nativeJdbcExtractor.getNativeResultSet(rs);
                //采用了接口,进行回调
                obj = rse.extractData(rsToUse);
                JdbcUtils.closeResultSet(rs);
                if(pss instanceof ParameterDisposer)
                    ((ParameterDisposer)pss).cleanupParameters();
                return obj;
                Exception exception;
                exception;
                JdbcUtils.closeResultSet(rs);
                if(pss instanceof ParameterDisposer)
                    ((ParameterDisposer)pss).cleanupParameters();
                throw exception;
            }

            final JdbcTemplate this$0;
            private final PreparedStatementSetter val$pss;
            private final ResultSetExtractor val$rse;

           
            {
                this$0 = JdbcTemplate.this;
                pss = preparedstatementsetter;
                rse = resultsetextractor;
                super();
            }
        }
);
    }

在对ResultSet进行回调处理的接口有三个,分别为RowMapper,ResultSetExtrator,RowHandlerCallBack接口
RowMapper接口中包含了一个mapRow方法,需要自己实现同通过转换从而得到自己想要的结果。
// 对resultset中封装一个接口为rowMapping
         List<VersionInfo> list = jdbcTemplate.query(sql, new
         RowMapper<VersionInfo>()
         {
         @Override
         public VersionInfo mapRow(ResultSet rs, int i) throws SQLException
         {
         VersionInfo versionInfo = new VersionInfo();
         versionInfo.setId(rs.getInt("id"));
         versionInfo.setVersionName(rs.getString("version_name"));
         versionInfo.setUploadTime(rs.getLong("upload_time"));
         versionInfo.setActiveState(rs.getString("active_state"));
         versionInfo.setVersionType(rs.getString("version_type"));
         versionInfo.setFilePath(rs.getString("file_path"));
         versionInfo.setReMark(rs.getString("remark"));
         versionInfo.setVersionNumber(rs.getString("version_number"));
         return versionInfo;
         }
         });



ResultSetExtrator接口中包含了extractData方法,该方法需要自己遍历Resultset才能得到想要的结果
  List<VersionInfo> list = (List<VersionInfo>) jdbcTemplate.query(sql,
         new ResultSetExtractor<List<VersionInfo>>()
         {
         @Override
         public List<VersionInfo> extractData(ResultSet rs) throws
         SQLException, DataAccessException
         {
         VersionInfo versionInfo = null;
         List<VersionInfo> list = new ArrayList<VersionInfo>();
         while (rs.next())
         {
         versionInfo = new VersionInfo();
         versionInfo.setId(rs.getInt("id"));
         versionInfo.setVersion_name(rs.getString("version_name"));
         versionInfo.setUpload_time(rs.getLong("upload_time"));
         versionInfo.setActive_state(rs.getString("active_state"));
         versionInfo.setVersion_type(rs.getString("version_type"));
         versionInfo.setFile_path(rs.getString("file_path"));
         versionInfo.setRemark(rs.getString("remark"));
         versionInfo.setVersion_number(rs.getString("version_number"));
         list.add(versionInfo);
         }
         return list;
         }
         });

RowCallbackHandler接口中包含了processRow方法,该方法中没有返回值,但是会自动的循环ResultSet结果集
final List<VersionInfo> list = new ArrayList<VersionInfo>();
        jdbcTemplate.query(sql, new RowCallbackHandler()
        {
            // 会自动循环ResultSet
            @Override
            public void processRow(ResultSet rs) throws SQLException
            {
                VersionInfo versionInfo = new VersionInfo();
                versionInfo.setId(rs.getInt("id"));
                versionInfo.setVersion_name(rs.getString("version_name"));
                versionInfo.setUpload_time(rs.getLong("upload_time"));
                versionInfo.setActive_state(rs.getString("active_state"));
                versionInfo.setVersion_type(rs.getString("version_type"));
                versionInfo.setFile_path(rs.getString("file_path"));
                versionInfo.setRemark(rs.getString("remark"));
                versionInfo.setVersion_number(rs.getString("version_number"));
                list.add(versionInfo);
            }
        });


可能大家会觉得奇怪,在查询方法中只传入的是ResultSetExtractor接口,而RowMapper和RowCallbackHandler接口与ResultSetExtractor没有相互的集成关系,那么jdbcTemlate是怎样做转换的
首先看下RowCallbackHandler接口

  public void query(String sql, PreparedStatementSetter pss, RowCallbackHandler rch)
        throws DataAccessException
    {
        query(sql, pss, ((ResultSetExtractor) (new RowCallbackHandlerResultSetExtractor(rch))));
    }


//传入的是RowCallbackHandler接口有一个RowCallbackHandlerResultSetExtractor类进行了转换该类实现了ResultSetExtractor接口

private static class RowCallbackHandlerResultSetExtractor
        implements ResultSetExtractor
    {

        public Object extractData(ResultSet rs)
            throws SQLException
        {
            for(; rs.next(); rch.processRow(rs));
            return null;
        }

        private final RowCallbackHandler rch;

        public RowCallbackHandlerResultSetExtractor(RowCallbackHandler rch)
        {
            this.rch = rch;
        }
    }

同理RowMapper

public class RowMapperResultSetExtractor
    implements ResultSetExtractor
{

    public RowMapperResultSetExtractor(RowMapper rowMapper)
    {
        this(rowMapper, 0);
    }

    public RowMapperResultSetExtractor(RowMapper rowMapper, int rowsExpected)
    {
        Assert.notNull(rowMapper, "RowMapper is required");
        this.rowMapper = rowMapper;
        this.rowsExpected = rowsExpected;
    }

    public List extractData(ResultSet rs)
        throws SQLException
    {
        List results = rowsExpected <= 0 ? ((List) (new ArrayList())) : ((List) (new ArrayList(rowsExpected)));
        int rowNum = 0;
        for(; rs.next(); results.add(rowMapper.mapRow(rs, rowNum++)));
        return results;
    }

    public volatile Object extractData(ResultSet resultset)
        throws SQLException, DataAccessException
    {
        return extractData(resultset);
    }

    private final RowMapper rowMapper;
    private final int rowsExpected;
}

猜你喜欢

转载自liuwuhen.iteye.com/blog/1634013