1.JDBC的使用
1、添加驱动获取数据库连接
2、创建ProperedStatement连接
3、执行SQL语句并处理返回结果
4、释放资源
String username="root"; String password="123"; String url="jdbc:mysql://localhost/test"; Connection con=null; Statement st=null; ResultSet rs=null; //1、获取连接 Class.forName("com.mysql.jdbc.Driver"); con=DriverManager.getConnection(url,username,password); //2、创建statement String sql="select * from test_user"; st=con.createStatement(); //3、执行sql语句并处理返回结果 rs=st.executeQuery(sql); while(rs.next()) { //对结果进行处理 } //4、释放资源 rs.close(); st.close(); con.close();
以上的例子是查询的一种方法,除了用Statement外,还可以用PreparedStatement,后者是前者的子类,在前者的基础上增加了预编译和防止sql注入的功能。另外,查询和增删是不同的用法,查询会返回ResultSet而增删改不会。
2.这样写代码有什么问题
2.1、这样的代码会造成大量重复劳动,比如获取连接,如果每个执行sql的方法都要写一遍相同的代码,那么这样的重复代码将充斥整个DAO层。
2.2、这样的代码可读性比较差,几十行代码真正和业务相关的其实就几行
2.3、大量重复代码会造成一个问题,那就是可维护性变差,一旦某个常量改变了。那么就需要把每个方法的该一遍,
2.4、数据库连接是重量级资源,每调用一次方法都去创建一个连接,性能会存在瓶颈。
3、如何改进
针对前面的问题中,改进的方法就是抽象,把可重用的代码抽象出去,单独组成一个模块,模块与模块之间实现解耦。由于整个JDBC操作流程分为4步,因此可以从这4步中下手去抽象。
3.1、获取数据库连接
我当时的解决方案是一次初始化很多连接放入list,然后用的时候取,现在的通用方法就是连接池,比如DBCP、C3P0等等。有兴趣的人可以去看看它们的源代码,看看是如何实现的
3.2、创建statement
我当时使用PreparedStatement进行处理,因为PreparedStatement会缓存已经编译过的sql
3.3、执行sql语句并处理返回结果
这块可以使用反射,将得到的结果封装成Java bean对象
3.4、释放资源
使用动态代理,改变connection的close方法的行为,将connection放回连接池
4.commons-dbutils的原理
一共有27个类,但真正常用的是三大组件十几个类:门面组件、结果处理组件和行处理组件,其中门面组件提供程序入口,并进行一些参数检验等,结果处理组件则是核心所在,因为返回的结果可以是map,可以是list可以是JavaBean,这一块的变化很大,所以抽象出一个组件出来应对这些变化,行处理组件是从结果处理组件中分离出来的,它是结果处理组件的基础,无论哪种处理器,最终都要与一行数据打交道,因此,单独抽象出这一组件。
类名 | 描述 |
门面组件 | |
QueryRunner | 执行增删改查的入口 |
结果处理组件 | |
ResultSetHandler | 用于处理ResultSet的接口 |
AbstractKeyedHandler | 将返回结果处理成键值对的抽象类 |
KeyedHandler | 处理数据库返回结果,封装成一个Map,数据库表的一个列名为key,通常可以用主键,数据库中的一行结果以Map的形式作为value |
BeanMapHandler | 处理数据库返回结果,封装成一个Map,和KeyedHandler的唯一的不同是,每一行结果以Javabean的形式作为value |
AbstractListHandler | 将返回结果处理成链表的抽象类 |
ArrayListHandler | 将返回结果处理成链表,这个链表的每个 元素都是一个Object数组,保存了数据库中对应的一行数据 |
ColumnListHandler | 如果要取单独一列数据,可以用这个handler,用户指定列名,它返回这个 列的一个list |
MapListHandler | 和ArrayListHandler不同的是,链表的每个元素是个Map,这个Map代表数据库里的一行数据 |
ArrayHandler | 将一行数据处理成object数组 |
BeanHandler | 将一行数据处理成一个Java bean |
BeanListHandler | 将所有数据处理成一个list,list的元素时Java bean |
MapHandler | 将一行结果处理成一个Map |
MapListHandler | 将所有结果处理成一个list,list的元素时Map |
ScalarHandler | 这个类常常用于取单个数据,比如某一数据集的总数等等 |
行处理组件 |
|
RowProcessor | 用于处理数据库中一行数据的接口 |
BasicRowProcessor | 基本的行处理器实现类 |
BeanProcessor | 通过反射将数据库数据转换成Javabean |
工具类 | |
DbUtils | 包含很多JDBC工具方法 |