1. 数据库连接池的整合
1)何为连接池?(内存中一块存储“可重用对象”的空间);
2)为什么使用连接池?(提高其性能-反复创建和销毁连接会带来很大的性能损耗);
3)为什么创建连接和销毁连接会有很大的性能损耗?(底层建立连接使用TCP/IP协议,基于此协议创建连接需要三次握手,释放连接需要四次挥手);
问题思考:
在C/S架构中,如何提高服务端响应的数据速度(降低响应时间)?
影响其响应性能(响应时间)的因素有哪些?
1)请求数据的传输时间?(数据量-压缩,带宽)
2)请求数据的处理时间?(架构,算法,CPU,磁盘)
3)响应数据的传输时间?(数据量-压缩,带宽,缓存)
4)响应数据的渲染时间?(html,css,js,images)
2. 池化思想
池化思想是我们项目开发过程中的一种非常重要的思想,如字符串池,整数池,对象池,线程池等都是池化思想的一种应用,都是通过复用对象,以减少因创建和释放对象所带来的资源消耗,进而来提升系统性能。例如Integer对象的内部池应用,代码如下:
packagecom.zhf.java.pool;
publicclassTestInteger01{
publicstaticvoidmain(String[]args) {
inta=10;
Integerb=10;
Integerb2=10;
Integerc=newInteger(10);
Integerc2=newInteger(10);
Integerd=Integer.valueOf("127");
Integere=Integer.valueOf(127);
Integeree=Integer.valueOf(127);
Integerf=Integer.valueOf(128);
Integerff=Integer.valueOf(128);
System.out.println(a==b);// true:int和Integer会自动转型比较int数值
System.out.println(b==b2);// true:虽然是引用,但是都是从Integer默认缓存池取出
System.out.println(b==c);// false:栈中常量和堆中对象
System.out.println(c==c2);// false:不同对象地址不同
System.out.println(b.equals(c));// true:值相同
System.out.println(d==e);// true:Integer.valueOf取出缓存池的对象
System.out.println(e==ee);// true:默认缓存池
System.out.println(f==ff);// false:常量池范围是-128~127,128超出常量池范围
}
}
3. 如果让你设计一个连接池,你会考虑哪些问题?
1)池的存储结构(物理存储结构)?(数组,链表)
2)从池中借,还连接的算法?
3)当池中没有连接时,基于什么方式处理连接请求?
4)池是可以共享的,我们需要考虑池在访问时的并发安全?
HikariCP底层存储连接使用的是数组结构,借和还都是随机的,线程安全应用到CAS算法
底层是CopyOnWriteArrayList()方法
4. Java中连接池的规范是什么?为什么要有规范?
1) 规范的定义:javax.sql.DataSource2) 使用规范可以让代码更严谨,其可维护性也会更好。
Java编程领域中所有连接池提供方,必须实现DataSource接口,后续我们编程时,可以通过此接口获取具体连接池对象。
5. Java中具体是哪个对象负责建立与数据库的连接?( Driver)
SpringBoot工程中想使用HikariCP连接池应该如何实现?
添加依赖(mysql , spring - data - JDBC)
配置连接数据库的url , username , password
在程序中耦合DataSource接口获取具体数据源对象
6. SpringBoot工程中基于HikariCP实现JDBC操作?
packagecom.zhf.goods.dao;
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Repository;
importjavax.sql.DataSource;
importjava.sql.*;
importjava.util.ArrayList;
importjava.util.HashMap;
importjava.util.List;
importjava.util.Map;
/**
* @author zhf
* @version 1.0
* @date 2020/12/1
*/
@Repository
publicclassDefaultGoodsDaoimplementsGoodsDao{
@Autowired
privateDataSourcedataSource;
privatestaticfinalLoggerlog=
LoggerFactory.getLogger(DefaultGoodsDao.class);
Map<String,Object>rowMap(ResultSetMetaDatarsmd,ResultSetrs)throwsSQLException{
Map<String,Object>map=newHashMap<>();
for(inti=1;i<=rsmd.getColumnCount();i++) {
map.put(rsmd.getColumnName(i),rs.getObject(rsmd.getColumnName(i)));
}
returnmap;
}
@Override
publicList<Map<String,Object>>findGoods() {
Connectionconn=null;
Statementstatement=null;
ResultSetrs=null;
Stringsql="select * from tb_goods";
try{
conn=dataSource.getConnection();
statement=conn.createStatement();
rs=statement.executeQuery(sql);
List<Map<String,Object>>list=newArrayList<>();
ResultSetMetaDatarsmd=rs.getMetaData();
while(rs.next()) {
// Map<String,Object> map = new HashMap<>();
// map.put("id",rs.getInt("id"));
// map.put("name", rs.getString("name"));
// map.put("remark", rs.getString("remark"));
// map.put("createdTime", rs.getTimestamp("createdTime"));
// list.add(map);
list.add(rowMap(rsmd,rs));
}
returnlist;
}catch(SQLExceptione) {
e.printStackTrace();
// log.info("查询异常!!" + e.getMessage());
log.error("查询异常,{}",e.getMessage());//{}表示占位符
thrownewRuntimeException("数据查询失败"+e.getMessage());//转换为非检查异常(编译时不检测的异常)
}finally{
// if (rs != null) try {
// rs.close();
// } catch (Exception e) {
// e.printStackTrace();
// }
// if (statement != null) try {
// statement.close();
// } catch (Exception e) {
// e.printStackTrace();
// }
// if (conn != null) try {
// conn.close();
// } catch (Exception e) {
// e.printStackTrace();
// }
close(rs,statement,conn);
}
}
publicvoidclose(ResultSetrs,Statementstatement,Connectionconn) {
if(rs!=null)try{
rs.close();
}catch(Exceptione) {
e.printStackTrace();
}
if(statement!=null)try{
statement.close();
}catch(Exceptione) {
e.printStackTrace();
}
if(conn!=null)try{
conn.close();
}catch(Exceptione) {
e.printStackTrace();
}
}
}
/**优点:
* 1)代码简单
* 2)使用了连接池,优化了建立连接的过程,从池中获取连接,提高了数据访问性能
* 3)使用了Map做映射,简化了pojo对象定义
*
* 缺点:
* 1) 可重用性比较差(如资源释放代码,可以封装)
* 2) 行映射不够灵活,太僵硬
* 3) 异常的处理不能简单打印一下
* 4) Map封装数据时值的类型不可控(建议后续修改为pojo对象)
* 5) 对共性模板应该进行封装,特性代码进行提取
* */
总结
总之,数据库连接池的为我们的项目开发及运行带来了很多优点,具体如下:
资源重用更佳。
由于数据库连接得到复用,减少了大量创建和关闭连接带来的开销,也大大减少了内存碎片和数据库临时进程、线程的数量,使得整体系统的运行更加平稳。
系统调优更简便。
使用了数据库连接池以后,由于资源重用,大大减少了频繁关闭连接的开销,大大降低了TIME_WAIT的出现频率。
系统响应更快。
数据库连接池在应用初始化的过程中一般都会提前准备好一些数据库连接,业务请求可以直接使用已经创建的连接,而不需要等待创建连接的开销。初始化数据库连接配合资源重用,使得数据库连接池可以大大缩短系统整体响应时间。
连接管理更灵活。
数据库连接池作为一款中间件,用户可以自行配置连接的最小数量、最大数量、最大空闲时间、获取连接超时间、心跳检测等。另外,用户也可以结合新的技术趋势,增加数据库连接池的动态配置、监控、故障演习等一系列实用的功能。