一前言:

以前刚开始用Java连接MySQL时,都是连猜带蒙的。比如:

一个Statement,Connection何时关闭?

Connection能不能先于Statement关闭?

ResultSet是怎样存放数据的?怎样才能高效操纵ResultSet?

PrepareStatement到底是怎样回事?

连接池是怎样工作的?

二、从JDBC driver代码分析:

在性能要求高的地方,应当使用ResultSet.get**(int)系列函数

如ResultSet.getBytes(String columnName),

则会先会调用findColumn(columnName)去查找到columnName对应的index是什么,而在findColumn(columnName)函数中,

会检查索引有没有构建好了,如果还没有则要构建columnName对应的索引。

所以,如果对性能要求,则应该使用ResultSet.getBytes(int column)函数。

PreparedStatement的缓存及重用

对于PreparedStatement,会有一个LRUCache来存放,会先到里面去取,拿不到再创建一个新的。

这个LRUCache的默认大小是25(太小了吧。。)。对于sql长度,如果大于256的,貌似则不缓存这个PreparedStatement。

LRUCache很简单,代码:

LinkedHashMap在每次put和putAll后,会调用removeEldestEntry来判断是否要移除最老的Entry。

LinkedHashMap的实现也比较简单,里面用双向链表把所有的Entry串在一起,当调用get时,把get所在的key移到链表的最前面。

PreparedStatement是如何实现重用的:

可见只是设置未关闭,再清除Parameters。所以从代码上来说,我们得到一个PreparedStatement在使用后,可以调用clearParameters,再接着使用。但是最好不要这样做。

如果是想要执行多次,可以用addBatch和executeBatch函数来多次执行。

关于CallableStatement和ServerPreparedStatement

CallableStatement,ServerPreparedStatement继承自PreparedStatement,实际上prepareStatement(String sql)函数返回的就是ServerPreparedStatement,LRUCache中放的也是。

CallableStatement也有一个LRUcache。

实际上当PreparedStatement调用close时,并没有真正释放掉资源,

Statement、Connection、ResultSet何时close

查看Statement的close函数代码,可以发现当close时,这个Statement中所有的ResultSet也会被close。

查看Connection的close函数,当close时,这个Connection的所有Statement都会被close。

但是据JDBC4的规范,有可能当Statement关闭时,ResultSet中的资源未被完全释放,当GC再次运行时才会回收。

所以最好就是顺序关闭ResultSet,Statement,Connection。

异常处理

SQLException是可以迭代的,应该用以下的代码来处理所有的异常:

在代码Connection类的很多地方,比如void closeAllOpenStatements()函数,可以看到这样的代码:

感觉这个是有问题的,因为把一些异常信息给丢掉了,实际上是可以迭代的,应该调用setNextException函数把异常都加到一起。

统计数量count:

代码中其它一些有意思的地方:

在代码中有大量的StringBuffer,而没有用StringBuilder,可能是要兼容JDK5的原因

配置都用一个ConnectionProperty类来表示,从这里派生出子类,IntegerConnectionProperty,BooleanConnectionProperty什么的。

每一个配置有都默认值,描述信息,版本等。貌似大部分在ConnectionProperties类中实现。

发现了代码中的一个bug,没有找到找交的地方,不是很重要就算了。

com.mysql.jdbc.ConnectionProperties类initializeFrom(String extractedValue)函数中:

三、从JDBC规范来看:

类型对照表:

注意:

在JDBC中要表示日期,是使用java.sql.Date,其日期格式是”年、月、日”;

要表示时间的话则是使用java.sql.Time,其时间格式为”时、分、秒”;

如果要表示”时、分、秒、微秒”的格式,则是使用java.sql.Timestamp

连接池可能会自动关闭之前的connection!

要注意使用连接池时,据JDBC规范:

A single physical PooledConnection object may generate many logical

Connection objects during its lifetime. For a given PooledConnection object,

only the most recently produced logical Connection object will be valid. Any

previously existing Connection object is automatically closed when the associated

PooledConnection.getConnection method is called. Listeners (connection

pool managers) are not notified in this case.

This gives the application server a way to take a connection away from a client.

This is an unlikely scenario but may be useful if the application server is trying

to force an orderly shutdown.

所以之前得到的Connection有可能会失效!!

但是实际上我估计没人会按这个方案来实现,因为太不友好,怎么能别人用着你就把它悄悄地关闭掉了。

测试了proxool,当设置最大Connection数为1时,在获取第二个Connection时,会抛出个异常。

物理连接和逻辑连接

连接池中分为物理连接和逻辑连接,对应PooledConnection类和Connection类。

PooledConnection不对用户暴露,当PooledConnection调用close时才关闭物理连接。

当Connection调用close时,并不真正关闭物理连接,只是把它放入池中。

Statement

Statement也分两种logical statement和physical statement。

可以实现PreparedStatement池,当Connection调用close时,并不把PreparedStatement关闭,有可能是放入到池中。

A pool of statements is associated with a PooledConnection object.

所以说一个物理连接都有一个Statement池。至于池的大小,可以通过ConnectionPoolDataSource的Properties来设置。

ConnectionPoolDataSource的属性

ConnectionPoolDataSource 有以下的标准属性:

maxStatements,initialPoolSize,minPoolSize,maxPoolSize,maxIdleTime,propertyCycle。

JDBC连接池的架构图和PreparedStatement池的架构图:

jdbc代码_Mysql Java 驱动代码阅读笔记及 JDBC 规范笔记相关推荐

  1. java美化代码快捷键,java编写代码常用快捷键

    在这个快节奏的社会中,做什么事情都讲求一个效率,自然是效率越高越好.Java程序员在编写代码时,高效工作的方法之一就是使用快捷键,那么编写代码常用快捷键都有哪些呢,这篇文章对java编写代码常用快捷键 ...

  2. 《编写高质量代码(改善Java程序的151个建议)》读书笔记

    嗯嗯,昨夜难眠,与Y君讲,要我遇些困苦,是要注定不凡的,我会走完一生的,要给自己些勇气. 2018.11.22 时间只是供我垂钓的溪流,在我喝着溪水的时候,我看的到它的沙床,它是那么浅啊,浅浅的洗漱流 ...

  3. java代码_Java:java五行代码实现Excel的快速导出

    通过Java进行excel导出,听着似乎有那么一点点的意思,也貌似很简单的样子(实事也很简单),究竟该怎么操作呢?但是如何进行操作呢,先看代码 再看效果 EasyExcel 本案例用到的框架是阿里推出 ...

  4. rabbitmq java代码_RabbitMQ java 原生代码

    rabbitMQ 的交换器有四种类型:direct.fanout.topic.headers 以下是具体的代码: direct:路由键只能全部匹配,才能进入到指定队列中.其他使用 direct生产者 ...

  5. mysql四列数据表代码_MySQL数据库常用代码

    MySQL数据库常用代码启动数据库服务:[ net Start MySQL ] 使用命令登录:[ Mysql -h localhost -u root -p] 关闭数据库服务: [net stop m ...

  6. 移植Nokia5110屏驱动 | 我是如何将51代码转为STM32驱动代码的

    大家好,我是程序员小哈. – 简介 问题由来 NOKIA 5110 屏 Nokia5110屏是一个非常经典的液晶显示模块,在小哈哥玩单片机的时候,可选的液晶模块并不多,一般来说就是LCD1602.LC ...

  7. 死锁是什么?死锁产生的条件?如何避免死锁?以及死锁的示例代码(Java代码)

    文章目录 一.什么是死锁? 二.产生死锁的条件? 三.产生死锁的示例代码(java) 四.如何避免死锁? 一.什么是死锁? 下面图片参考 JavaGuide中的内容: 死锁的概念: 死锁:指的是相互两 ...

  8. Java新手之Java 从代码到运行的过程

    为什么80%的码农都做不了架构师?>>>    转自51cto.com 写程序的得将代码的执行过程牢记于心,了解了规则,才能更好的写出健全,高效的代码. Java 从代码到运行的过程 ...

  9. 树莓派博通BCM2835芯片手册导读及io口驱动代码的实现

    树莓派博通BCM2835芯片手册导读及io口驱动代码的实现 树莓派寄存器的介绍 寄存器地址问题 驱动代码的实现 在linux中生成树莓派所需要的的程序及实现现象 一.树莓派寄存器的介绍 GPFSEL0 ...

  10. linux驱动之一、LED驱动(驱动代码小结附:github代码链接)

    文章目录 一.相关知识点(涉及接口.结构体.调用关系等) 1.1 裸机开发步骤与驱动开发过程对比 1.1.1 裸机开发步骤 1.1.2 Linux系统下LED驱动开发步骤 1.2 预备知识:写驱动时涉 ...

最新文章

  1. 图像抠图算法学习 - Shared Sampling for Real-Time Alpha Matting
  2. 在IE右键菜单,添加图片保存快捷方式
  3. 高性能分布式计算与存储系统设计概要(上)(转)
  4. Linux系统正则表达式用法笔记
  5. Linux格式化分区的命令
  6. shiro学习(16):使用注解实现权限认证和后台管理二
  7. 借力阿里云存储产品 延锋彼欧加速数字化重塑
  8. python 角度传感器模拟_python树莓派红外反射传感器
  9. jquery-文档处理
  10. 魅族17系列正式发布:17年梦想之作,3699元起
  11. [mysql] C++操作mysql方法
  12. HDU3544 不平等博弈
  13. android xml java混合编程_Java学习中注解与多线程,网络编程与XML技术
  14. word2vec C源码解析
  15. lisp ssget 浩辰_ssget 详解
  16. IP地址和mac地址的区别
  17. Moneybookers的优点
  18. ICCV2019超分辨率方向论文整理笔记
  19. 01路径规划问题的相关理论
  20. 远控免杀专题(12)-Green-Hat-Suite免杀(VT免杀率23/70)

热门文章

  1. 【原创·总结】影响sql查询性能的因素
  2. asp页面实现301重定向方法
  3. 汇编语言数据段查找ASCII码并回显
  4. 异常值检测——绝对中位差MAD(median absolute deviation )
  5. 手机信令数据在城市规划领域的应用
  6. 国产卫星高分四号(GF4)预处理(辐射定标)
  7. 数据结构------图-----深度广度优先遍历
  8. CSDN九年的博客时光
  9. Myeclipse打包生成jar文件 A exception has Occured问题解决
  10. 我35岁了,依然可以“横行职场”