通过对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 ...
随机推荐
- Linux(centos)环境下Lamp环境搭建,成功版。
搭建环境必须条件:1.Linux环境,2.Apache,3.mysql ,4.PHP,搭建步骤如下 1.开启Linux,得到root权限:sudo su 接下来输入登录密码,进入root权限,因为安装 ...
- Mysql查询优化小结
转自http://www.cnblogs.com/112ba/p/6220650.html 数据类型 简单原则:更小更好,简单就好,避免NULL1)整型如int(10)括号中的值与存储大小无关2)实数 ...
- uva 10391
这个题,单纯做出来有很多种方法,但是时间限制3000ms,因此被TL了不知道多少次,关键还是找对最优解决方法,代码附上: #include<bits/stdc++.h> using nam ...
- babel的使用详解
由于es6的很多特性在旧的浏览器下支持不好,我们在使用的时候需要将其转化为es5,下面介绍babel解析器的使用 一:独立使用babel的方法 1.本地安装babel-cli npm install ...
- 【JAVA零基础入门系列】Day3 Java基本数据类型
前两篇已经将开发环境搭建完成,如果你已经按之前的教程按部就班的完成了部署,那么世界上最优秀的编程语言之一和世界上最优秀的IDE之一已经出现在你的电脑上(此处应有掌声),如果你还没入门,或者正在台阶上踱 ...
- MMORPG战斗系统随笔(三)、AI系统简介
在设计一款游戏的时候,如果我们是玩家,是希望自己能够操作角色畅玩游戏的.在一款MMORPG游戏中,大部分的实际游戏角色,是需要玩家来操作的,通过在游戏大世界相互完成游戏中的任务等等来体验游戏.在大世界 ...
- 全方位解读及介绍windows网络安全及常见攻击方式
本来我就是来逛逛论坛的,可是看到前面有位一样是干网络安全的同行,留下来过的痕迹,发了一篇相对不错的文章,我寻思咱既然来这一趟,也不能显得就比别人差啊.所以我也就写了这一片不算成熟小文章,望各位共勉之哈 ...
- 让EditPlus支持SQL高亮提示
将文件放在一个确定的位置,不要放在桌面这些临时位置.然后在 EditPlus 的菜单栏选择 工具(T) -> 配置用户工具(C) 选择左边"类别"中的 文件 -> 设置 ...
- django集成celery之callback方式link_error和on_failure
在使用django集成celery进行了异步调度任务之后,如果想对失败的任务进行跟踪或者告警,怎么做? 这里提供一个亲测的方法. 1.任务callback 假如你想在任务执行失败的时候,打印错误信息并 ...
- Spring ——依赖注入配置一些知识点
依赖注入 依赖注入的原理与实现 依赖注入(DI)和依赖查找(Dependency Lookup)共同组成 控制反转(IoC).从原理的角度来说,依赖注入和控制反转是没 有不同的,可以看作是从两个角度来 ...