通过对DAO层的封装减少数据库操作的代码量
在学框架之前,写项目时总是要花大量的时间去写数据库操作层代码,这样会大大降低我们的效率,为了解决这个问题,我花了两天时间利用反射机制和泛型将DAO层进行了封装,这样我们只需要写sql语句,不需要再写繁琐的数据库操作语句,增强代码的复用性,让我们把主要精力放在业务逻辑上。
以下就是我写的代码(我是用连接池操作,普通的jdbc操作和连接池道理相同,主要思想是将结果集设置到对象的属性中)
/**
* 预处理通用查询对象集合
*
* @param cla 操作类型
* @param params 预处理参数
* @param sql 要执行的sql语句
* @return 返回的对象集合
* @throws SQLException 抛出异常
*/
@SuppressWarnings("deprecation")
public static <T> List<T> commonPreparedQueryList(final Class<T> cla,Object params[],String sql) throws SQLException{
//获得连接池(这里使用的是阿里巴巴开源的jar包)
QueryRunner qr = new QueryRunner(DBUtil.getDruid());
/*
* 声明一个List存放返回对象
*/
List<T> tList = new ArrayList<T>();
/*
* 执行查询操作并返回对应集合,传入sql和预处理参数并进行结果集处理(这里要实现handle方法)
*/
tList = qr.query(sql, params,new ResultSetHandler<List<T>>(){ public List<T> handle(ResultSet rs) throws SQLException {
/*
* 这里要用到ResultSetMetaData来获取数据库表的字段名和数量
*/
ResultSetMetaData ms = rs.getMetaData();
2 T t = null;//声明一个泛型,此处类型和传入一致
List<T> list = new ArrayList<T>();
/*
* 通过循环获得表中所有的字段名,并通过反射的方式把字段名内容
* 设置到我们要查询的集合中,并将结果返回
* 注意:这里需要用到循环的嵌套,我们需要先循环表中所有数据,
* 然后再循环表的所有字段名
*/
while(rs.next()){
try {
t = cla.newInstance();//创建一个实例化对象
//获得所有字段名,并将其转换为驼峰式命名规则 eg:guest_id转化为guestId
for(int i = 0; i <ms.getColumnCount(); i++){
String columnName = ms.getColumnName(i+1);//获得字段名
/*
* 以下操作是将下划线形式转化为驼峰式的实现
* 现将字段名以下划线分割到字符串数组中,将第一个数组元素复制到StringBuffer中
* 然后将后面的数组元素第一个首字母转化为大写形式,最后将他们拼接到一起,将所得结果转化为字符串
*/
String[] strName = columnName.split("_");
StringBuffer sb = new StringBuffer(strName[0]);
for(int i1 = 1;i1<strName.length;i1++){
strName[i1] = strName[i1].substring(0, 1).toUpperCase().concat(strName[i1].substring(1));
sb.append(strName[i1]);
}
String property = sb.toString();
/*
* 获得对象的所有属性,并将结果集中的内容通过反射赋值到对象的属性中
*/
Field field = cla.getDeclaredField(property);
field.setAccessible(true);
field.set(t, rs.getObject(columnName));
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
//将对象添加到List中
list.add(t);
}
//循环结束后返回对象集合
return list;
} });
return tList;
}
测试代码:
public void Test() throws SQLException{
List<Book> bookList = new LinkedList<Book>();
Object params[] = new Object[]{"%三%"};
String sql = "select * from book where book_name like ? ";
bookList = CommonDao.commonPreparedQueryList(Book.class,params ,sql);
System.out.println(bookList);
}


一共两条数据
查询一条数据(这个和查询集合的区别只有集合需要循环结果集,而这个只需要用if语句判断一下即可,其余代码完全相同):
/**
* 通用预处理查询对象
*
* @param cla
* @param params
* @param sql
* @return 对象
* @throws SQLException
* @throws InstantiationException
* @throws IllegalAccessException
*/
@SuppressWarnings("deprecation")
public static <T> T commonPreparedQuery(final Class<T> cla,Object params[],String sql) throws SQLException, InstantiationException, IllegalAccessException{
QueryRunner qr = new QueryRunner(DBUtil.getDruid());
T m = cla.newInstance();
m = qr.query(sql,params ,new ResultSetHandler<T>(){ public T handle(ResultSet rs) throws SQLException {
ResultSetMetaData rm = rs.getMetaData();
T t = null;
try {
if(rs.next()){ //这里用if,是与查询集合代码的唯一区别
t = cla.newInstance();
for(int i = 0; i<rm.getColumnCount(); i++){
String columnName = rm.getColumnName(i+1);
String str[] = columnName.split("_");
StringBuffer sb = new StringBuffer(str[0]);
for(int j = 1; j<str.length; j++){
str[j] = str[j].substring(0, 1).toUpperCase().concat(str[j].substring(1));
sb.append(str[j]);
}
String property = sb.toString();
Field field = cla.getDeclaredField(property);
field.setAccessible(true);
field.set(t, rs.getObject(columnName));
}
}else{
System.out.println("sql语句错误或对象不存在");
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return t;
} });
return m;
}
测试:
public void Test() throws SQLException, InstantiationException, IllegalAccessException{
Book book = new Book();
Object params[] = new Object[]{10001};
String sql = "select * from book where book_id = ? ";
book = CommonDao.commonPreparedQuery(Book.class, params, sql);
System.out.println(book);
}

还有普通查询操作(不通过预处理)
这种方式和预处理查询的唯一区别只是不需要传递参数params,其余和上面代码完全一致
/**
* 通用类查询集合
*
* @param cla
* @param sql
* @return
* @throws SQLException
*/
public static <T> List<T> commonQueryList(final Class<T> cla,String sql) throws SQLException{
QueryRunner qr = new QueryRunner(DBUtil.getDruid());
List<T> tList = new ArrayList<T>();
tList = qr.query(sql, new ResultSetHandler<List<T>>(){ public List<T> handle(ResultSet rs) throws SQLException {
ResultSetMetaData ms = rs.getMetaData();
T t = null;
List<T> list = new ArrayList<T>();
while(rs.next()){
try {
t = cla.newInstance();
for(int i = 0; i <ms.getColumnCount(); i++){
String columnName = ms.getColumnName(i+1);
String[] strName = columnName.split("_");
StringBuffer sb = new StringBuffer(strName[0]);
for(int i1 = 1;i1<strName.length;i1++){
strName[i1] = strName[i1].substring(0, 1).toUpperCase().concat(strName[i1].substring(1));
sb.append(strName[i1]);
}
String property = sb.toString();
Field field = cla.getDeclaredField(property);
field.setAccessible(true);
field.set(t, rs.getObject(columnName));
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
list.add(t);
}
return list;
} });
return tList;
}
测试:
public void Test() throws SQLException{
List<Book> bookList = new LinkedList<Book>();
String sql = "select * from book ";
bookList = CommonDao.commonQueryList(Book.class,sql);
System.out.println(bookList);
}


同样有两条数据
查询一个对象:
/**
* 查询一个数据库类操作
*
* @param cla
* @param sql
* @return 一个数据库类对象
* @throws SQLException
* @throws InstantiationException
* @throws IllegalAccessException
*/
public static <T> T commonQuery(final Class<T> cla,String sql) throws SQLException, InstantiationException, IllegalAccessException{
QueryRunner qr = new QueryRunner(DBUtil.getDruid());
T m = cla.newInstance();
m = qr.query(sql, new ResultSetHandler<T>(){ public T handle(ResultSet rs) throws SQLException {
ResultSetMetaData rm = rs.getMetaData();
T t = null;
try {
if(rs.next()){
t = cla.newInstance();
for(int i = 0; i<rm.getColumnCount(); i++){
String columnName = rm.getColumnName(i+1);
String str[] = columnName.split("_");
StringBuffer sb = new StringBuffer(str[0]);
for(int j = 1; j<str.length; j++){
str[j] = str[j].substring(0, 1).toUpperCase().concat(str[j].substring(1));
sb.append(str[j]);
}
String property = sb.toString();
Field field = cla.getDeclaredField(property);
field.setAccessible(true);
field.set(t, rs.getObject(columnName));
}
}else{
System.out.println("sql语句错误或对象不存在");
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return t;
} });
return m;
}
测试:
@Test
public void Test() throws SQLException, InstantiationException, IllegalAccessException{
Book book = new Book();
String sql = "select * from book where book_id = 10002";
book = CommonDao.commonQuery(Book.class,sql);
System.out.println(book);
}

接下来是增删改操作,这个操作比较简单,不需要用到泛型和反射,只需要传入sql语句即可:
public static boolean updateSql(String sql) throws SQLException{
boolean flag = false;
QueryRunner qr = new QueryRunner(DBUtil.getDruid());
//执行修改操作
if(qr.update(sql)>0)
flag = true;
return flag;
}
还有预处理形式
public static boolean updatePreparedSql(String sql,Object params[]) throws SQLException{
boolean flag = false;
QueryRunner qr = new QueryRunner(DBUtil.getDruid());
if(qr.update(sql,params)>0)
flag = true;
return flag;
}
还有批量处理形式
/**
* 通过预处理解决批量增删改操作
*
* @param sql
* @param params params[rows][cols],rows代表sql语句执行次数,cols表示替换占位符的参数个数
* @return boolean
* @throws SQLException
*/
public static boolean batchProcessing(String sql,Object params[][]) throws SQLException{
boolean flag = false;
QueryRunner qr = new QueryRunner(DBUtil.getDruid());
if(qr.batch(sql, params).length == params.length)
flag = true;
return flag;
}
通过对DAO层的封装减少数据库操作的代码量的更多相关文章
- 关于dao层的封装和前端分页的结合(文章有点长,耐心点哦)
任何一个封装讲究的是,实用,多状态.Action: 任何一个Action继承分页有关参数类PageManage,自然考虑的到分页效果,我们必须定义下几个分页的参数.并根据这个参数进行查值. 然 ...
- 带分页功能的SSH整合,DAO层经典封装
任何一个封装讲究的是,使用,多状态.Action: 任何一个Action继承分页有关参数类PageManage,自然考虑的到分页效果,我们必须定义下几个分页的参数.并根据这个参数进行查值. 然 ...
- 八:SpringBoot-集成JPA持久层框架,简化数据库操作
SpringBoot-集成JPA持久层框架,简化数据库操作 1.JPA框架简介 1.1 JPA与Hibernate的关系: 2.SpringBoot整合JPA Spring Data JPA概述: S ...
- Entity Framework 实体框架的形成之旅--几种数据库操作的代码介绍(9)
本篇主要对常规数据操作的处理和实体框架的处理代码进行对比,以便更容易学习理解实体框架里面,对各种数据库处理技巧,本篇介绍几种数据库操作的代码,包括写入中间表操作.联合中间表获取对象集合.递归操作.设置 ...
- Java通过JDBC 进行Dao层的封装
前言 前面有一章节,我专门讲解了Java通过JDBC 进行MySQL数据库操作,这主要讲解了MySQL数据库的连接和简单的操作,但是在真正的Java项目中,我们要不断的和数据库打交道,为了提高数据库操 ...
- JavaEE中的MVC(一)Dao层彻底封装
最近Android工作实在难找,考虑是不是该转行做Java了,今天开始,花几天的事件,研究一下JavaEE各层优化. 首先是Dao层 增删改方法封装 使用PreparedStatement执行一条Sq ...
- SpringBoot2.0 基础案例(09):集成JPA持久层框架,简化数据库操作
一.JAP框架简介 JPA(Java Persistence API)意即Java持久化API,是Sun官方在JDK5.0后提出的Java持久化规范.主要是为了简化持久层开发以及整合ORM技术,结束H ...
- php 封装mysql 数据库操作类
<?phpheader('content-type:text/html;charset=utf-8');//封装mysql 连接数据库php_mysql//封装mysql 连接数据库ph ...
- php 封装Mysql数据库操作类
花了点时间写了个基于php5.3的Mysql类 $mysql = new Mysql('host','user','pass','db') bool Mysql::insert("表&quo ...
随机推荐
- jQuery自定义插件--banner图滚动
前言 jQuery是一个功能强大的库,提供了开发JavaScript项目所需的所有核心函数.很多时候我们使用jQuery的原因就是因为其使用插件的功能,然而,有时候我们还是需要使用自定义代码来扩展这些 ...
- Day2 基本数据类型
一.python数据类型 1.1数字 2 是一个整数的例子. 长整数 不过是大一些的整数. 3.23和52.3E-4是浮点数的例子.E标记表示10的幂.在这里,52.3E-4表示52.3 * 10-4 ...
- MySQL所学所思所想
MySQL更改线上配置方案思想:原则上,需要备机.备份工作准备到位,有参数调优配置方案.有配置回退方案.有应急切换备机方案.以上方案评审无问题,然后可以和客户约定实施的时间.服务中断时间,先向客户侧申 ...
- 深入浅出AQS之条件队列
相比于独占锁跟共享锁,AbstractQueuedSynchronizer中的条件队列可能被关注的并不是很多,但它在阻塞队列的实现里起着至关重要的作用,同时如果想全面了解AQS,条件队列也是必须要学习 ...
- Python数据分析(二): Numpy技巧 (1/4)
In [1]: import numpy numpy.__version__ Out[1]: '1.13.1' In [2]: import numpy as np
- AMD、CMD、CommonJs规范
AMD.CMD.CommonJs规范 将js代码分割成不同功能的小块进行模块化的概念是在一些三方规范中流行起来的,比如CommonJS.AMD和CMD.接下来我们看一下这几种规范. 一.模块化规范 C ...
- Linux修改hostname的几种方法
修改hostname有几种方式 1: hostname DB-Server --运行后立即生效(新会话生效),但是在系统重启后会丢失所做的修改 ...
- c# gdi+输出成不同mime类型的图片
/// <summary> /// 通过图片的mime类型得到相应的编码器 /// </summary> /// <param name="mimeType&q ...
- 关于Android SDK Manager无法获取更新列表的正确设置
1.以"管理员身份运行"SDK Manager. 2.Android SDK Manager"=>"Tools"=>"Optio ...
- Echarts数据可视化grid直角坐标系(xAxis、yAxis),开发全解+完美注释
全栈工程师开发手册 (作者:栾鹏) Echarts数据可视化开发代码注释全解 Echarts数据可视化开发参数配置全解 6大公共组件详解(点击进入): title详解. tooltip详解.toolb ...