通过对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 ...
随机推荐
- FS BPM 业余研发(用户详细操作手册--单人串行/并行)之 深圳分公司技术部请假审批流程
1.FS BPM 简介 BPM软件中BPM是英文字母缩写,大致有二个意思.第一.Business Process Management,即业务流程管理,是一套达成企业各种业 务环节整合的全面管理模式. ...
- angular 学习笔记
每天进步一点点,学习笔记 笔记来自 angular权威指南 如果想要屏蔽浏览器对表单的默认验证行为,可以在表单元素上添加 novalidate 标记. 而按钮标签则完全忽略 hr e f 属性,并不 ...
- Oracle的trim( )、ltrim( )、rtrim( )三个函数的用法及注意事项
学习一下用法整理trim().ltrim().rtrim()的用法 trim().ltrim().rtrim()三个函数有两个作用,分别是: 一.去除字符串前后空格(基本用法) trim(string ...
- Opengl4.5 中文手册—A
因为opengl API 比较庞大,网络上还没有完整的.较新的opengl中文手册 这对很多人很不方便,所以整理了这一系列,用于帮助大家"快速浏览最新的opengl api" 为了 ...
- ThinkPHP中,display和assign用法详解
thinkphp 模板显示display和assign的用法 $this->assign('name',$value); //在 Action 类里面使用 assign 方法对模板变量赋值,无论 ...
- Finding LCM (最小公倍数)
Finding LCM Time Limit: 2000MS Memory Limit: 32768KB 64bit IO Format: %lld & %llu [Submit] ...
- 1289 大鱼吃小鱼 1305 Pairwise Sum and Divide 1344 走格子 1347 旋转字符串 1381 硬币游戏
1289 大鱼吃小鱼 有N条鱼每条鱼的位置及大小均不同,他们沿着X轴游动,有的向左,有的向右.游动的速度是一样的,两条鱼相遇大鱼会吃掉小鱼.从左到右给出每条鱼的大小和游动的方向(0表示向左,1表示向右 ...
- node-Telnet
什么是Telnet(window系统) 使用Telnet工具作为客户端对创建的TCP服务器进行会话交流时遇到的问题做一个简单的记录.希望可以帮助到一些同学. 这里看一下百度词条的解释 Telnet协议 ...
- PS 软件操作应用处理——粒子化任务效果
前 言 JRedu 上次分享中,给大家介绍了一些图片的处理方法,主要是通过滤镜里的功能,把图片处理成素描效果或者水彩画效果,营造出不同的氛围. PS是一款非常强大的软件,包含了非常多的功能,合成 ...
- M-移动端的webapp页面布局教程和webapp实战分析
http://www.25xt.com/html5css3/8092.html 响应式设计 1 媒体查询 适用于不同固定宽度设计 媒体类型 : screen 屏幕 print 打印机 handheld ...