Druid06-SQL执行

1、连接对象的封装

​ 如果没有配置Filter 则生成具体的连接对象返回,否则将Connection对象包装成 ConnectionProxyImpl。

    public Connection createPhysicalConnection(String url, Properties info) throws SQLException {
        Connection conn;
        if (getProxyFilters().isEmpty()) {
            //通过驱动获取Connection
            conn = getDriver().connect(url, info);
        } else {
            //执行责任链,并将连接对象封装成ConnectionProxyImpl
            conn = new FilterChainImpl(this).connection_connect(info);
        }
        createCountUpdater.incrementAndGet(this);
        return conn;
    }
2、ConnectionProxyImpl 对象

​ ConnectionProxyImpl 对 Connection 的方法进行了重写,创建的 Statement 和 PreparedStatement 对象 (StatementProxyImpl、PreparedStatementProxyImpl) 都进行了扩展,基于多态的思想提高了代码的扩展性。

    public Statement createStatement() throws SQLException {
        //创建责任链
        FilterChainImpl chain = createChain();
         //执行责任链并将对象封装成 StatementProxyImpl
        Statement stmt = chain.connection_createStatement(this);
        //重置责任链
        recycleFilterChain(chain);
        return stmt;
    }

    public PreparedStatement prepareStatement(String sql) throws SQLException {
        //创建责任链
        FilterChainImpl chain = createChain();
        //执行责任链并将对象封装成 PreparedStatementProxyImpl
        PreparedStatement stmt = chain.connection_prepareStatement(this, sql);
        //重置责任链
        recycleFilterChain(chain);
        return stmt;
    }
3、Statement 对象

​ 在Druid 中将连接对象被包装成会对Statement对象进行包装, 获取到 Statement 时被包装成 DruidPooledStatement,获取PreparedStatement 对象时被装成 DruidPooledPreparedStatement。

    public Statement createStatement() throws SQLException {
   		//先检查当前连接的状态
        checkState();
        Statement stmt = null;
        try {
            stmt = conn.createStatement();
        } catch (SQLException ex) {
            handleException(ex, null);
        }
		//设置SQL执行的超时时间
        holder.getDataSource().initStatement(this, stmt);
        //对Statement对象包装成DruidPooledStatement
        DruidPooledStatement poolableStatement = new DruidPooledStatement(this, stmt);
        holder.addTrace(poolableStatement);
        return poolableStatement;
    }

 	public PreparedStatement prepareStatement(String sql) throws SQLException {
        //先检查当前连接的状态
        checkState();
        PreparedStatementHolder stmtHolder = null;
        //通过SQL生成Statement缓存KEY
        PreparedStatementKey key = new PreparedStatementKey(sql, getCatalog(), MethodType.M1);
        //是否开启Statement缓存
        boolean poolPreparedStatements = holder.isPoolPreparedStatements();
        if (poolPreparedStatements) {
            //基于LinkedHashMap实现LRUCache中获取
            stmtHolder = holder.getStatementPool().get(key);
        }
        if (stmtHolder == null) {
            try {
                //获取PreparedStatement通过PreparedStatementHolder进行包装
                stmtHolder = new PreparedStatementHolder(key, conn.prepareStatement(sql));
                holder.getDataSource().incrementPreparedStatementCount();
            } catch (SQLException ex) {
                handleException(ex, sql);
            }
        }
        //设置超时时间和使用次数+1
        initStatement(stmtHolder);
        //对PreparedStatementHolder对象包装成DruidPooledPreparedStatement
        DruidPooledPreparedStatement rtnVal = new DruidPooledPreparedStatement(this, stmtHolder);
        holder.addTrace(rtnVal);
        return rtnVal;
    }

​ 1、缓存PreparedStatement,本质上就是缓存游标,SQL语句增删改查都是游标操作,只是游标指向的目标值不同。

​ 2、缓存的本质是使用空间换取时间,通过Druid监控后台查看PSCache的命中率 ,当命中率非常低就不推荐使用。

​ 3、poolPreparedStatements 设置为true ,并且指定每个连接上PSCache的大小。

​ 4、maxPoolPreparedStatementPerConnectionSize 需要进行权衡,设置过小导致命中率很低,设置过大会占用大量内存。

​ 5、MySQL 5.5之后开始支持PSCache,MySQL PSCache是Connection 级别。

4、SQL执行
public ResultSet executeQuery() throws SQLException {
    firstResultSet = true;
    updateCount = null;
    //SQL语句
    lastExecuteSql = sql;
    //SQL执行类型
    lastExecuteType = StatementExecuteType.ExecuteQuery;
    //执行SQL开始时间-初始化
    lastExecuteStartNano = -1L;
    //执行SQL的耗时-初始化
    lastExecuteTimeNano = -1L;
    //创建责任链并执行 SQL
    return createChain().preparedStatement_executeQuery(this);
}

​ Druid 通过对JDBC Connection 和Statement 等对象进行了进一步的封装就可以实现对不同数据库的支持,其次通过封装可以增强和扩展更多的功能特性。

5、Filter

​ 将不同业务逻辑块放一起,然后进行链式调用,Filter通常是FilterChain形式串在一起,可以无侵入的框架扩展。

说明
Filter接口定义数据库操作的方法,比如连接,提交,回滚,完整操作。
FilterChain接口责任链接口,定义与Filter接口类似,只是说接收的参数有所区别。
FilterAdapter类实现Filter接口,实现了大部分的方法,基本都是statement的相关实现。
FilterManager类管理加载责任链的实现。
FilterEventAdapter类实现Filter接口的大部分方法,提供了更规范的方式来完成对连接和 statement 前置和后置处理。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值