JDBC项目实践与源码解析(七)

JDBC项目实践与源码解析——执行sql

本专栏为系列文章,如果想要系统学习JDBC,作者建议从第一篇文章,顺序读完全部文章。
文中项目源码地址:https://github.com/bethanwang/jdbc-study

1. 执行sql

在创建了Statement对象以后,通过调用其executeQuery()方法,执行sql语句。

String sql = "select s.*,c.clazz_name from student s left join clazz c on s.clazz_id=c.clazz_id";
rs = sta.executeQuery(sql);

此处其实是调用com.mysql.cj.jdbc.StatementImpl类中的executeQuery(sql)方法。

源码解析:

com.mysql.cj.jdbc.StatementImpl类:

package com.mysql.cj.jdbc;

public class StatementImpl implements JdbcStatement {

  /** The current results */
  protected ResultSetInternalMethods results = null;
  
	@Override
  public java.sql.ResultSet executeQuery(String sql) throws SQLException {
    synchronized (checkClosed().getConnectionMutex()) {
      /*
       省略代码...
       */
      this.results = ((NativeSession) locallyScopedConn.getSession())
        .execSQL(this, sql, this.maxRows, null, createStreamingResultSet(),                                                                         				 			getResultSetFactory(), cachedMetaData, false);
      /*
       省略代码...
       */
      return this.results;
    }
  }

}

结合源码可以看到,其实是在executeQuery方法中,通过locallyScopedConn.getSession()这一行代码获得了数据库会话(Session),然后执行sql,将查询结果封装到ResultSetInternalMethods中。

​ 另外源码中获取数据库会话(Session)并和数据库交互的代码都放到了synchronized的代码块中,所以如果程序中只有一个数据库链接(Connection),程序每次访问数据库的过程中,当前线程都会独占该数据库链(Connection)接资源,只有当前线程结束对数据库的访问(或访问超时),其他线程才能利用该数据库链接(Connection)访问数据库;因此,系统中一般使用数据库连接池来管理数据库的连接,数据库连接池中会持有一定数量的数据库链接(Connection),避免只有一个数据库链接(Connection)造成的并发瓶颈。

​ 因此,系统中一般使用数据库连接池来管理数据库的连接,数据库连接池中会持有一定数量的数据库链接(Connection),避免只有一个数据库链接(Connection)造成的并发瓶颈。

数据库连接池,会在以后的文中讲解。

2. 处理查询结果集

查询的数据集合封装在ResultSet中,遍历ResultSet集合将数据封装成List<Student>

List<Student> list = new ArrayList<Student>();
while(rs.next()){
  Student s = new Student();
  s.setMajor(rs.getString("major"));
  s.setName(rs.getString("name"));
  s.setStuNo(rs.getString("stu_no"));
  Clazz c = new Clazz();
  c.setClazzId(rs.getInt("clazz_id"));
  c.setClazzName(rs.getString("clazz_name"));
  s.setClazz(c);
  list.add(s);
}
//遍历从数据库中查询的对象集合
list.forEach(s->{
  System.out.println(s.toString());
});

3. 关闭数据库连接

因为代码执行过程中,可能出现异常,所以关闭数据库连接的代码写在finally块中;此处是一个单元测试,测试完需要关闭数据库链接,在系统中可以不用关闭,避免重复创建数据库链接带来的消耗。

try {
  //省略代码...
} catch(Exception e){
  e.printStackTrace();
} finally {
  /* conn/sta/set都有可能是null,所以在使用这几个对象之前先判断是否是null */
  if(conn != null){
    try {
      conn.close();
    } catch(Exception e){
      e.printStackTrace();
    }
  }
  if(sta != null){
    try {
      sta.close();
    } catch(Exception e){
      e.printStackTrace();
    }
  }
  if(rs != null){
    try {
      rs.close();
    } catch(Exception e){
      e.printStackTrace();
    }
  }
}

上一篇:JDBC深入讲解——创建会话
下一篇:实现动态窗口——新建DBUtil类

受作者水平限制,文中难免有不足之处,若读者阅读过程中发现问题,还望及时指正,感谢支持!
​ 作者邮箱:547317812@qq.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Captain-船长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值