在学框架之前,写项目时总是要花大量的时间去写数据库操作层代码,这样会大大降低我们的效率,为了解决这个问题,我花了两天时间利用反射机制和泛型将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层的封装减少数据库操作的代码量的更多相关文章

  1. 关于dao层的封装和前端分页的结合(文章有点长,耐心点哦)

    任何一个封装讲究的是,实用,多状态.Action:     任何一个Action继承分页有关参数类PageManage,自然考虑的到分页效果,我们必须定义下几个分页的参数.并根据这个参数进行查值. 然 ...

  2. 带分页功能的SSH整合,DAO层经典封装

    任何一个封装讲究的是,使用,多状态.Action:     任何一个Action继承分页有关参数类PageManage,自然考虑的到分页效果,我们必须定义下几个分页的参数.并根据这个参数进行查值. 然 ...

  3. 八:SpringBoot-集成JPA持久层框架,简化数据库操作

    SpringBoot-集成JPA持久层框架,简化数据库操作 1.JPA框架简介 1.1 JPA与Hibernate的关系: 2.SpringBoot整合JPA Spring Data JPA概述: S ...

  4. Entity Framework 实体框架的形成之旅--几种数据库操作的代码介绍(9)

    本篇主要对常规数据操作的处理和实体框架的处理代码进行对比,以便更容易学习理解实体框架里面,对各种数据库处理技巧,本篇介绍几种数据库操作的代码,包括写入中间表操作.联合中间表获取对象集合.递归操作.设置 ...

  5. Java通过JDBC 进行Dao层的封装

    前言 前面有一章节,我专门讲解了Java通过JDBC 进行MySQL数据库操作,这主要讲解了MySQL数据库的连接和简单的操作,但是在真正的Java项目中,我们要不断的和数据库打交道,为了提高数据库操 ...

  6. JavaEE中的MVC(一)Dao层彻底封装

    最近Android工作实在难找,考虑是不是该转行做Java了,今天开始,花几天的事件,研究一下JavaEE各层优化. 首先是Dao层 增删改方法封装 使用PreparedStatement执行一条Sq ...

  7. SpringBoot2.0 基础案例(09):集成JPA持久层框架,简化数据库操作

    一.JAP框架简介 JPA(Java Persistence API)意即Java持久化API,是Sun官方在JDK5.0后提出的Java持久化规范.主要是为了简化持久层开发以及整合ORM技术,结束H ...

  8. php 封装mysql 数据库操作类

    <?phpheader('content-type:text/html;charset=utf-8');//封装mysql   连接数据库php_mysql//封装mysql   连接数据库ph ...

  9. php 封装Mysql数据库操作类

    花了点时间写了个基于php5.3的Mysql类 $mysql = new Mysql('host','user','pass','db') bool Mysql::insert("表&quo ...

随机推荐

  1. Ansible系列(七):执行过程分析、异步模式和速度优化

    本文目录:1.1 ansible执行过程分析1.2 ansible并发和异步1.3 ansible的-t选项妙用1.4 优化ansible速度 1.4.1 设置ansible开启ssh长连接 1.4. ...

  2. js中如何在一个函数里面执行另一个函数

    1.js中如何在函数a里面执行函数b function a(参数c){ b(); } function b(参数c){ } 方法2: <script type="text/javasc ...

  3. Oracle第一波

    html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,bi ...

  4. Android Studio安装应用时报错 installation failed with message Failed to finalize session......

    解决方法: 在AndroidManifest.xml中的provider中的authorities后加几个数字即可. 2017.09.01: 我发现有的项目AndroidManifest.xml中没有 ...

  5. 支持向量机SVM(一)

    [转载请注明出处]http://www.cnblogs.com/jerrylead 1 简介 支持向量机基本上是最好的有监督学习算法了.最开始接触SVM是去年暑假的时候,老师要求交<统计学习理论 ...

  6. 使用Scrapy创建一个爬虫

    使用Scrapy创建一个爬虫 创建项目 您可以使用下面的命令来创建 Scrapy 项目: scrapy startproject 项目名称 例:scrapy startproject scrapy_p ...

  7. Ubuntu中MongoDB安装

    在Ubuntu中MongoDB有时候启动不起来,可以参考以下方法从新安装: 1.导入包管理系统使用的公钥 Ubuntu 的软件包管理工具(即dpkg和APT)要求软件包的发布者通过GPG密钥签名来确保 ...

  8. Intellij idea史上最简单的教程之Linux下安装与破解Intellij idea2017

    一.前言 这一节我们介绍在Linux下如何安装与破解Intellij idea2017.现在有很多公司开发环境都是Linux,所以掌握在Linux环境下使用Idea办公也是咱们必须得掌握的技能. 记住 ...

  9. Struts201---环境搭配

    开发工具:Eclipse   Struts版本:2.3.24 最近在学SSH框架,SSH是 struts+spring+hibernate的一个集成框架,是目前比较流行的一种Web应用程序开源框架.集 ...

  10. ch1-使用路由-静态资源-404页面-ejs模板

    1 package.json 项目文件夹根目录创建这个文件 //要依赖的模块 "dependencies": { //dependency 依赖的复数形式 "expres ...