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