对于Java数据库的连接,由最初学习的每次全部手工代码,到后面的不断利用知识简化代码量;这是不断学习的过程,就像人类由原始社会的钻木取火到当代的文明,都是一步步过来的!

本文不从最开始的JDBC入门开始总结,只总结被很多人忽略的地方:自己写框架,或者更确切说是框架的原理!

先说使用框架的好处,也可以说是使用工具的好处,就如同使用记事本编程和eclipse之间的区别,很明显使用工具大大的提高了我们的编程效率,使我们在编程时候可以几乎避免垃圾代码或重复代码的痛苦!

但是这样做其实也有不好的地方:不少的程序员,尤其是初学者,贪恋短时间出成果的短暂虚荣,学习不求原理,只求方便。也就造成了很多有识之士口中所说的:离开SSH框架,你还能做出来什么?诚然编程工具可以促进我们的学习,但是如果我们沉溺于简单的皮毛,一辈子也就是碌碌无为的码农!其实一句话:向往高处走,底层必须学!

本文总结:自己如何编写JDBC框架,实现重复代码的简化?

本文默认使用C3P0连接池,从用C3P0连接池写过增删改查四个操作分析比较后开始!

之前我们写的CRUD操作,可以看到重复了很多的代码,我们想我们能否提炼这三个方法使其成为一个方法,只是根据不同的参数来确定去执行什么操作?

实现这一设想,我们首先来学习一些必备的知识:就是说我们如何知道我们数据库中的表的信息,当然如果你是表的创始人你知道,但是假如现在我们是框架师,我们对sql,对表一无所知,(或者说我们了解SQL知识,但是对数据库内容根本无法知晓)我们只是使用一些技术实现对数据库的操作,所以如何得到数据库相关信息的呢?

通过元数据!

先了解元数据

所谓元数据就是指数据库、表、列的定义信息,(描述数据的数据)如何获得元数据呢?

DataBaseMetaData(数据库元数据)

使用connection.getDatabasemetaData()方法,那这个DataBaseMetaData对象到底有什么属性或者方法呢?

数据库的元数据

getURL():返回一个String类对象,代表数据库的URL。

getUserName():返回连接当前数据库管理系统的用户名。

getDatabaseProductName():返回数据库的产品名称。

getDatabaseProductVersion():返回数据库的版本号。

getDriverName():返回驱动驱动程序的名称。

getDriverVersion():返回驱动程序的版本号。

isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。

ParameterMetaData(获取参数元数据)

可用于获取关于PreparedStatement 对象中每个参数标记的类型和属性信息的对象。使用PreparedStatement.getParameterMetaData()方 法 获 得 代 表PreparedStatement元 数 据 的ParameterMetaData对象。

它有两个最重要的方法:

getParameterCount() 获得指定参数的个数

getParameterType(intparam) 获得指定参数的sql类型(MySQL驱动不支持该方法)

ResultSetMetaData(获取结果集元数据)

可用于获取关于ResultSet对象中列的类型和属性信息的对象。有关 ResultSet 中列的名称和类型的信息。 

那么如果是向把返回的结果遍历一下封装到bean当中我们如何设置呢,我们又不知道key和value,这个时候我们就需要另外一个元数据了,ResultSetMetaData它可以获得使用ResultSet对象元数据的对象,主要方法包括:

getColumnCount() 返回resultset对象的列数

getColumnName(intcolumn) 获得指定列的名称

getColumnTypeName(intcolumn) 获得指定列的类型

实例:(我们的框架)

对CUD操作,我们集成到一个update方法去,根据参数的不同,进行不同的操作!

//利用元数据+反射优化CRUD操作!这个的原理和DBUtils的几乎一样!

创建JavaBean,用来封装数据。(查询时候用的上)

package com.itheima.domain;

public class User {

private int id;

private String username;

private String password;

private java.util.Date birthday;

private float salary;

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getUsername() {

return username;

}

public void setUsername(String username) {

this.username = username;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

public java.util.Date getBirthday() {

return birthday;

}

public void setBirthday(java.util.Date birthday) {

this.birthday = birthday;

}

public float getSalary() {

return salary;

}

public void setSalary(float salary) {

this.salary = salary;

}

}

package com.itheima.dao;

import java.sql.Connection;

import java.sql.ParameterMetaData;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.ResultSetMetaData;

import java.sql.SQLException;

import org.apache.commons.beanutils.BeanUtils;

import com.itheima.domain.User;

import com.itheima.util.JdbcUtil;

public class Demo2 {

public static void main(String[] args) throws Exception {

/*//这是Insert

String sql = "insert into user (username,password,birthday,salary)values(?,?,?,?)";

Object params[] = {"zhangsan","125","2012-8-25",6000};

update(sql,params);*/

/*//尝试Update

String sql = "update user set username = ? where username = ?";

Object params[] = {"lisi","zhangsan"};

update(sql,params);

//此时就可以感受到好处:对某类操作(CUD)等只需要简单的sql语句变换(就是说很少的变化),减轻了代码量

*/

//尝试Delete

/*String sql = "delete from user where id = ?";

update(sql,new Object[]{2});

假如update也不是你写的,这样的话代码量就大大的减少了!这样就引出了框架

*/

/*

 * 进行的是查询操作

* 查询为什么需要javabean?因为查询需要返回数据,不然怎么显示

 */

String sql = "select * from user where id = ?";

User user = (User)query(sql, new Object[]{1}, User.class);

System.out.println("用户名:" + user.getUsername());

System.out.println("密码:" + user.getPassword());

System.out.println("生日:" + user.getBirthday().toLocaleString());

System.out.println("薪水:" + user.getSalary());

}

private static Object query(String sql, Object[] params ,Class clazz) throws Exception {

Object obj = clazz.newInstance();

Connection conn = JdbcUtil.getMySqlConnection();

PreparedStatement pstmt = conn.prepareStatement(sql);

//获取参数元数据

ParameterMetaData psmd = pstmt.getParameterMetaData();

int size = psmd.getParameterCount();

//循环绑定

for (int i = 0; i < size; i++) {

pstmt.setObject(i+1, params[i]);

}

ResultSet rs = pstmt.executeQuery();

if(rs.next()){

//取得结果集元数据

ResultSetMetaData rsmd = rs.getMetaData();

//取得结果集列数目

size = rsmd.getColumnCount();

for (int i = 0; i < size; i++) {

//获取列名

String columnName = rsmd.getColumnName(i+1);

//取得结果集元数据之后通过BeanUtils框架为JavaBean设置值

BeanUtils.setProperty(obj, columnName, rs.getObject(i+1));

}

}

JdbcUtil.close(rs);

JdbcUtil.close(pstmt);

JdbcUtil.close(conn);

return obj;

}

//CUD操作(通用做法)

private static void update(String sql, Object[] params) throws SQLException {

Connection conn = JdbcUtil.getMySqlConnection();

PreparedStatement pstmt = conn.prepareStatement(sql);

ParameterMetaData psmd = pstmt.getParameterMetaData();

int size = psmd.getParameterCount();

System.out.println(size);

//循环绑定对象的值(就是将?与实际的传入参数绑定)绑定第一个,第二个...

for (int i = 0; i < params.length; i++) {

pstmt.setObject(i+1, params[i]);

}

//执行

pstmt.executeUpdate();

JdbcUtil.close(pstmt);

JdbcUtil.close(conn);

}

}

总结:此时我们可以看到,使用元数据确实很大程度上减少了重复代码量。但是针对我们自己的框架,肯定还有不完美的小问题。

这时候注意:java是一门开源的语言,这是java保持强大生命力的根本所在,既然我们能想到自己写一个框架来简化操作,那么肯定有开源组织也注意到了,而且做得更好!

再总结一个知识点:

O-R-Mapping  object-relative-mapping

对象关系映射。把关系型数据映射为对象(只要能将传统的关系数据库的操作,映射为面向对象方式操作的框架都可以称为OR-Mapping)

常用O-R Mapping映射工具

Hibernate

Ibatis

Commons DbUtils(只是对JDBC简单封装)

Apache—DBUtils框架

简介:

commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。因此dbutils成为很多不喜欢hibernate的公司的首选。

API介绍:

org.apache.commons.dbutils.QueryRunner 

org.apache.commons.dbutils.ResultSetHandler

工具类

org.apache.commons.dbutils.DbUtils。   

QueryRunner类 

该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。

QueryRunner类提供了两个构造方法:

默认的构造方法(无参)

另一个需要一个 javax.sql.DataSource 来作参数的构造方法。

ResultSetHandler 接口的实现类

ArrayHandler:把结果集中的第一行数据转成对象数组。

ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。

BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。

BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。

ColumnListHandler:将结果集中某一列的数据存放到List中。

KeyedHandler(name):将结果集中的每一行数据都封装到一个Map<列名,列值>里,再把这些map再存到一个map里,其key为指定的key。

MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。

MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List

利用DButils框架进行操作:(使用相当简单,但是注意理解原理)

package com.itheima.dao;

import java.sql.SQLException;

import org.apache.commons.dbutils.QueryRunner;

import org.apache.commons.dbutils.handlers.BeanHandler;

import com.itheima.domain.User;

import com.itheima.util.JdbcUtil;

public class Demo3 {

public static void main(String[] args) throws Exception {

//使用DButil框架

QueryRunner runner = new QueryRunner(JdbcUtil.getDataSource());

//String sql = "update user set username = ? where username = ?";

String sql = "insert into user (username,password,birthday,salary)values(?,?,?,?)";

//runner.update(sql, new Object[]{"wangwu","lisi"});

runner.update(sql, new Object[]{"zhangzetian","2356","2012-02-11",6000});

sql = "select * from user where id = ?";

User user = (User) runner.query(sql, 1, new BeanHandler(User.class));

System.out.println("用户名:" + user.getUsername());

}

}

这样的写法是不是相当的简单呢!

备注:配置文件,数据库,Utils工具类等已经提前准备好。

本文章只是自己学西过程中的总结,并不是讲解类型的博文,所以这些东西没有面面俱到的写出!

黑马程序员—创建JDBC框架及原理分析的更多相关文章

  1. 黑马程序员_Java集合框架

    集合类 1,为什么出现集合类? 面向对象语言对食物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式. 2,数组和集合类同是容器,有何不同? 数组 ...

  2. 黑马程序员——C语言开门片内存分析

    iOS培训,iOS学习---------型技术博客.期待与您交流!------------ 一.各种进制的总结 1.二进制 (1) 在c语言中二进制以0b开头,输出二进制格式没有固定的格式,自定义输出 ...

  3. 黑马程序员——【Java高新技术】——代理

    ---------- android培训.java培训.期待与您交流! ---------- 一.“代理概述”及“AOP概念” (一)代理概述 1.问题:要为已存在的多个具有相同接口的目标类的各个方法 ...

  4. 黑马程序员:轻松精通Java学习路线连载1-基础篇!

    编程语言Java,已经21岁了.从1995年诞生以来,就一直活跃于企业中,名企应用天猫,百度,知乎......都是Java语言编写,就连现在使用广泛的XMind也是Java编写的.Java应用的广泛已 ...

  5. 课程4:黑马程序员_spring2.5视频教程--视频列表

    \黑马程序员_spring2.5视频教程\01Struts相关基础理论介绍.mp4; \黑马程序员_spring2.5视频教程\02搭建struts开发环境.mp4; \黑马程序员_spring2.5 ...

  6. 黑马程序员:Java基础总结----反射

    黑马程序员:Java基础总结 反射   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 反射 反射的基石:Class类 Class类代表Java类,它的各个实例对象又分别 ...

  7. 【黑马18期Java毕业生】黑马程序员Java全套资料+视频+工具

        Java学习路线图引言:        黑马程序员:深知广大爱好Java的人学习是多么困难,没视频没资源,上网花钱还老被骗. 为此我们历时一个月整理这套Java学习路线图,不管你是不懂电脑的小 ...

  8. 黑马程序员+SQL基础(上)

    黑马程序员+SQL基础 ---------------<a href="http://edu.csdn.net"target="blank">ASP ...

  9. 黑马程序员:Java基础总结----泛型(高级)

    黑马程序员:Java基础总结 泛型(高级)   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 泛型(高级) 泛型是提供给javac编译器使用的,可以限定集合中的输入类型 ...

随机推荐

  1. hdu3068之manacher算法+详解

    最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  2. MVC数组模型绑定

    ASP.NET MVC数组模型绑定   在ASP.NET MVC中使用Razor语法可以在视图中方便地展示数组,如果要进行数组模型绑定,会遇到索引断裂问题,如下示例: <input type=& ...

  3. 我写过的软件之FileExpert

    公司要做一个项目,跟MP4有点关系.到网上找了规范文档看了看,理解还是不够深入.干脆花点时间做一个Parser.取名FileExpert.眼下仅仅支持解析ISO_IEC_14496-12的文件格式.取 ...

  4. php反射类 ReflectionClass

    什么是php反射类,顾名思义,能够理解为一个类的映射.举个样例: class fuc {        //定义一个类static function ec() {echo '我是一个类';}}$cla ...

  5. C++习题 虚函数-计算图形面积

    C++习题 虚函数-计算图形面积 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 122  Solved: 86 [cid=1143&pid=6 ...

  6. 主要的核心思想是取cookie然后发查询请求,不需要浏览器做代理(转)

    需求是催生项目和推进项目的不竭动力. 背景: 最近,因为媳妇要做个B超检查,想着去大医院查查应该更放心,所以就把目标瞄准在A医院.早已耳闻A院一号难求万人空巷,所以把所有能接触到的机会都看了一遍,线下 ...

  7. 关于埃博拉(Ebola)基础研究病毒

    关于埃博拉(Ebola)病毒的基础研究 2005年.美国哈佛大学医学研究院(Harvard Medical School)James Cunningham教授关于埃博拉病毒有一项基础研究,研究成果发表 ...

  8. 三层架构与MVC

    三层简介 先说说Web三层架构这个古老话题.地球人都知道web三层架构是指: • >用户接口层(UI Layer) • >业务逻辑层(Bussiness Layer) • >持久化层 ...

  9. 编写高效的JavaScript

    Web前端性能优化——编写高效的JavaScript   前言 随着计算机的发展,Web富应用时代的到来,Web 2.0早已不再是用div+css高质量还原设计的时代.自Gmail网页版邮件服务的问世 ...

  10. 通过angularjs的directive以及service来实现的列表页加载排序分页(转)

    前两篇:(列表页的动态条件搜索,我是如何做列表页的)分别介绍了我们是如何做后端业务系统数据展示类的列表页以及动态搜索的,那么还剩下最重要的一项:数据展示.数据展示一般包含三部分: 数据列头 数据行 分 ...