实现自己的JDBC框架
使用JDBC操作数据库时,dao层的增删改查有很多重复的代码,比如下面的
public int getTotal() {
Connection conn = null;//通用代码
PreparedStatement ps = null;//通用代码
ResultSet rs = null;//通用代码
try {
conn = ...//获取连接//通用代码
ps = conn.prepareStatement("select count(*) from blog");//只有sql语句不同
rs = ps.executeQuery();
if (rs.next()) {
return rs.getInt(1);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
rs.close();//通用代码
ps.close();//通用代码
conn.close();//通用代码
} catch (SQLException e) {
e.printStackTrace();
}
}
return 0;
}
如果做一个简单的增删改查,会发现很多代码都是通用的,如果重复使用无疑会让代码显得很冗余
如果使用框架开发,框架会帮我们省去这些麻烦,或者有很多开源的工具类也可以比如apache的DBUtil工具类
不过看了黑马的教学视频,感觉完全可以自定义一个JDBC框架来帮我们省去很多麻烦(虽然我是造轮子,不过学习初期造轮子还是很有帮助的)
自定义JDBC框架
对于增删改里面重复的代码最多,且不包含结果集(查询包含的结果集需要封装,所以单独定义),用update方法统一代表增删改,query方法代表查询
对于过程,我们发现用JDBC增删改查里面只有sql语句不一样,sql语句里的占位符又会不一样,所以考虑自定义方法里传入参数包含sql语句和sql语句中需要传入的参数(用数组表示),对于查询由于需要封装结果集到Bean中,但是Bean类实现不知道,所以无法直接封装,考虑使用策略模式
下面直接上代码,具体解释留在注释中
由于使用了DBCP数据源,所以用的DBCP数据源获取数据库连接,这里就不上DBCP的代码了
主类DBAssist
public class DBAssist {
//设置连接从数据源获取
//也可以不使用数据源,自己随便定义个Connection连接
private DataSource ds;
public DBAssist(DataSource ds){
this.ds=ds;
}
//增删改
public void update(String sql,Object[] params){
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
try{
conn=ds.getConnection();//得到链接
ps=conn.prepareStatement(sql);
//设置参数,
//ParameterMetaData方法获取参数信息
ParameterMetaData pmd=ps.getParameterMetaData();
//获取sql语句中的占位符?个数
int parameterCount=pmd.getParameterCount();
//获取的参数个数与传入的参数个数比较
if(parameterCount>0){
if(params==null||params.length<1)
throw new IllegalArgumentException("the parameter is wrong");
if(params.length!=parameterCount)
throw new IllegalArgumentException("the parameter is wrong");
for(int i=0;i<parameterCount;i++){
ps.setObject(i+1, params[i]);
}
}
ps.executeUpdate();
}catch(Exception e){
throw new DBAssistException(e);
}finally{
release(conn,ps,rs);
}
}
//查询,由于不知道具体的Bean类,考虑使用策略模式
//ResultSetHandler为抽象出的策略接口,策略类需继承该类以完成封装
//策略类框架会给出实现
public Object query(String sql,Object[] params,ResultSetHandler rsh){
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
try{
conn=ds.getConnection();
ps=conn.prepareStatement(sql);
ParameterMetaData pmd=ps.getParameterMetaData();
int parameterCount=pmd.getParameterCount();//sql语句中的占位符个数
if(parameterCount>0){
if(params==null||params.length<1)
throw new IllegalArgumentException("the parameter is wrong");
if(params.length!=parameterCount)
throw new IllegalArgumentException("the parameter is wrong");
for(int i=0;i<parameterCount;i++){
ps.setObject(i+1, params[i]);
}
}
//得到查询结果集
rs=ps.executeQuery();
//封装结果集到对象中去,这里使用策略模式,最好提供实现类(类似于注册器)
return rsh.handler(rs);
}catch(Exception e){
throw new DBAssistException(e);
}finally{
release(conn,ps,rs);
}
}
//关闭连接
private void release(Connection conn,Statement stmt,ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs=null;
}
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt=null;
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
conn=null;
}
}
}
此时已经可以用update方法进行增删改的功能了
对于查询,query方法中的策略接口代码如下
public interface ResultSetHandler {
public Object handler(ResultSet rs);
}
具体策略类有两个,分别用来查询单行和查询多行(利用反射填充Bean中的字段)
public class BeanHandler implements ResultSetHandler {
private Class<? extends Object> clazz;
public BeanListHandler(Class<? extends Object> clazz) {
this.clazz = clazz;
}
public List<Object> handler(ResultSet rs) {
try {
List<Object> list = new ArrayList<Object>();
while (rs.next()) {
Object bean = clazz.newInstance();
//查询数据库中的元数据信息
ResultSetMetaData rsmd = rs.getMetaData();
int count = rsmd.getColumnCount();
for (int i = 0; i < count; i++) {
String columnName = rsmd.getColumnName(i + 1);
Object columnValue = rs.getObject(i + 1);
Field field = clazz.getDeclaredField(columnName);
field.setAccessible(true);
field.set(bean, columnValue);
}
list.add(bean);
}
return list;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
)
//bean中字段名必须与数据库中字段名一致
public class BeanListHandler implements ResultSetHandler {
private Class<? extends Object> clazz;
public BeanHandler(Class<? extends Object> clazz) {
this.clazz=clazz;
}
//查询单记录
public Object handler(ResultSet rs) {
try {
Object bean=clazz.newInstance();
if(rs.next()){
ResultSetMetaData rsmd=rs.getMetaData();
int count=rsmd.getColumnCount();
for(int i=0;i<count;i++){
String columnName=rsmd.getColumnName(i+1);
Object columnValue=rs.getObject(i+1);
Field field=clazz.getDeclaredField(columnName);
field.setAccessible(true);
field.set(bean,columnValue);
}
return bean;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
Bean类
public class Blog {
private int id;
private int category_id;
private String title;
private String content;
private Date created_time;
...
//getter和setter方法
@Override
public String toString() {
return "Blog [id=" + id + ", category_id=" + category_id + ", title=" + title + ", content=" + content
+ ", created_time=" + created_time + "]";
}
}
自定义异常类
public class DBAssistException extends RuntimeException {
public DBAssistException() {
}
public DBAssistException(String message) {
super(message);
}
public DBAssistException(Throwable cause) {
super(cause);
}
public DBAssistException(String message, Throwable cause) {
super(message, cause);
}
public DBAssistException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
最后测试下
public void update(){
String sql="update blog set created_time=? where id=?";
dba.update(sql, new Object[]{new Date(System.currentTimeMillis()),1});
}
//查询单行记录测试
public void query(){
String sql="select * from blog";
Blog blog=(Blog) dba.query(sql, null,new BeanHandler(Blog.class));
System.out.println(blog.getTitle().length());
}
//查询多行记录测试
@SuppressWarnings("unchecked")
public List<Blog> query2(){
String sql="select * from blog";
List<Blog> list=(List<Blog>) dba.query(sql, null,new BeanListHandler(Blog.class));
return list;
}
public static void main(String args[]) {
BlogDao test = new BlogDao();System.out.println(test.update());
test.query();
List<Blog> list=test.query2();
for(Blog l:list){
System.out.println(l);
}
}
}
实现自己的JDBC框架的更多相关文章
- java web学习总结(二十三) -------------------编写自己的JDBC框架
一.元数据介绍 元数据指的是"数据库"."表"."列"的定义信息. 1.1.DataBaseMetaData元数据 Connection.g ...
- Spring的JDBC框架
转自: http://www.cnblogs.com/windlaughing/p/3287750.html Spring JDBC提供了一套JDBC抽象框架,用于简化JDBC开发. Spring主要 ...
- 【总结】编写自己的JDBC框架
一.数据库连接池: 在一般用JDBC 进行连接数据库进行CRUD操作时,每一次都会: 通过:java.sql.Connection conn = DriverManager.getConnection ...
- jdbc框架 commons-dbutils+google guice+servlet 实现一个例子
最近闲着无聊,于是看了一下jdbc框架 commons-dbutils与注入google guice. 我就简单的封装了一下代码,效率还是可以的.... jdbc+google guice+servl ...
- JDBC 学习笔记(四)—— 自定义JDBC框架+Apache—DBUtils框架+事务管理+操作多表
本文目录: 1.自定义JDBC框架 ——数据库元数据:DataBaseMetaData 2.自定义JDBC框架 ——数据库元数据:DataBaseMetaData ...
- javaweb学习总结(四十)——编写自己的JDBC框架
一.元数据介绍 元数据指的是"数据库"."表"."列"的定义信息. 1.1.DataBaseMetaData元数据 Connection.g ...
- JDBC框架
一.元数据介绍 元数据指的是"数据库"."表"."列"的定义信息. 1.1.DataBaseMetaData元数据 Connection.g ...
- 编写自定义的JDBC框架与策略模式
本篇根据上一篇利用数据库的几种元数据来仿造Apache公司的开源DbUtils工具类集合来编写自己的JDBC框架.也就是说在本篇中很大程度上的代码都和DbUtils中相似,学完本篇后即更容易了解DbU ...
- 黑马程序员—创建JDBC框架及原理分析
对于Java数据库的连接,由最初学习的每次全部手工代码,到后面的不断利用知识简化代码量:这是不断学习的过程,就像人类由原始社会的钻木取火到当代的文明,都是一步步过来的! 本文不从最开始的JDBC入门开 ...
随机推荐
- Javascript实例技巧精选(8)—计算当月剩余天数
>>点击这里下载完整html源码<< 截图如下: 利用Javascript在网页上计算当前月份的剩余天数,相应代码如下: <script language="J ...
- 附加被分离DB
如何附加被分离的质疑数据库? 简介 有些时间,由于日志损坏等原因,导致了数据库质疑.如果此时你分离了数据库,那你会发现你无法再附加上数据库,那后果还是很严重的.因此本文提供了一种方式,可以使得当数 ...
- 快速创建InfoPath表单
快速创建InfoPath表单 2010年已经过去了一半了,这时候再说初识InfoPath可能会被很多人笑话,但是又有多少人真正认识InfoPath呢?无论你是刚刚 听说这个东西还是它的老相好都请同我一 ...
- Hashtable Dictionary List
Hashtable Dictionary List 谁效率更高 一 前言 很少接触HashTable晚上回来简单看了看,然后做一些增加和移除的操作,就想和List 与 Dictionary比较下存 ...
- 安装xdebug后var_dump输出没有格式化的问题
在ubuntu10.04下面配置Apache2.2 + PHP5.3的开发环境,顺便装了一个xdebug扩展方便调试代码. 但是环境配置好了之后却发现xdebug加载成功了但是var_dump输出的内 ...
- Linux环境进程间通信(四):信号灯
linux下进程间通信的几种主要手段: 管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允 ...
- ios7学习之路六(隐藏状态栏 )
方法一(代码设置): 现在ios7已经更改为透明,并且不占用屏幕高度.其中隐藏及显示的方法如下: 在uiviewcontroller的子类下,调用: if ([self respondsTo ...
- 我的第一篇文章 —— IE6的那些css常见bug(汇总)
我的微博终于在前几天建立了 虽说很早之前就知道博客园这个地方 但怕自己不能坚持去写一些东西一直没有建.这几天 我做了这个决定 把我的博客建起来 每周发一些看到的,听到了一些前端知识或者前沿技术. 另外 ...
- Alfred工具
神兵利器——Alfred 有人的地方就有江湖,有江湖就有纷争. 很多人说我的文字风格相对轻松和温和,那是因为我很早就认识到,我们没有教育脑残和喷子的义务.在网际多年,看过太多虚拟的刀锋和鲜血,很多人被 ...
- 【Machine Learning】单参数线性回归 Linear Regression with one variable
最近开始看斯坦福的公开课<Machine Learning>,对其中单参数的Linear Regression(未涉及Gradient Descent)做个总结吧. [设想] ...