手把手封装数据层之DataUtil数据库操作的封装
上一篇我们写完了数据库连接的封装
没有看的请移步上一篇关于数据库连接的内容
这次我们讲数据库操作的封装。数据库的操作就是增删改查;心再大一点就可以直接分为查询和其他。
因为查询是有返回对象的,而其他都不用返回值(事实是可以返回执行该语句所影响数据表中的行数,但是用处不大,仅做判断用)
话不多说,看代码,代码比较长,但是我大概写了一些注释,有理解不到位的地方还请指正
package com.yck.database;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DataUtil
{
/**
* 以List的形式返回多条查询语句的结果
* @param clazz
* @param sql
* @param objects
* @return
*/
@SuppressWarnings("rawtypes")
public static <T> List<T> selectForBeanList(Class clazz,String sql,Object...objects)
{
List<T> list = new ArrayList<T>();
List<Map<String,Object>> mapList = queryForMapList(sql,objects);
for(Map<String,Object> map:mapList )
{
list.add(queryForBean(map, clazz));
}
return list;
}
/**
* 以javabean 对象的形式返回从数据空中查找出来的单条数据
* @param clazz
* @param sql
* @param objects
* @return
*/
@SuppressWarnings("rawtypes")
public static <T>T selectForBean(Class clazz,String sql,Object...objects)
{
Map<String,Object> map = queryForMap(sql,objects);
return queryForBean(map,clazz);
}
/**
* 除了查询外,都用这个
* @param updateSQL
* @param objects
* @return
*/
public static int updata(String updateSQL,Object...objects)
{
Connection conn = DButil.getConnection(); //建立与数据库的连接
PreparedStatement pStam = null;
int result = 10;
try
{
pStam = DButil.prepareStatement(conn, updateSQL);
for(int i=0;i<objects.length;i++) //对sql语句的通配符?进行填充
{
pStam.setObject(i+1, objects[i]);
}
result = pStam.executeUpdate(); //得到update结果
} catch (SQLException e)
{
e.printStackTrace();
}finally
{
DButil.closePreparedStatement(pStam);
DButil.closeConnection(conn);
}
return result;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private static <T>T queryForBean(Map<String,Object> map, Class clazz)
{
T obj = null;
Field field = null;
try
{
obj = (T) clazz.newInstance(); //实例化一个clazz对象
} catch (InstantiationException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
if(map == null)
return null;
for(String columnName:map.keySet()) //遍历map的key
{
Method method = null;
String propertyName = StringUtil.columnToProperty(columnName); //将存在map中的key值转化成bean中的属性字段,驼峰命名
try
{
field = clazz.getDeclaredField(propertyName); //在类clazz中匹配相应的字段信息
} catch (NoSuchFieldException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
String fieldType = field.toString().split(" ")[1]; //将字段信息以空格分割,第二条为字段类型(0 是第一条,一般为private)
Object value = map.get(columnName); //得到相应的值
if(value == null)
{
continue;
}
String setMethodName ="set"+StringUtil.upperCaseFirstCharacter(propertyName); //拼接set方法
String valueType = value.getClass().getName();
if(!fieldType.equalsIgnoreCase(valueType)) //根据类型转换value值
{
if(fieldType.equalsIgnoreCase("java.lang.Integer"))
{
value =Integer.parseInt(String.valueOf(value));
}
else if(fieldType.equalsIgnoreCase("java.lang.String"))
{
value = String.valueOf(value);
}
else if(fieldType.equalsIgnoreCase("java.util.Date"))
{
valueType = "java.lang.Date";
String datestr = String.valueOf(value);
Timestamp ts = Timestamp.valueOf(datestr);
Date date = new Date(ts.getTime());
value = date;
}
}
try
{
method = clazz.getDeclaredMethod(setMethodName, Class.forName(fieldType));
method.invoke(obj, value);
} catch (NoSuchMethodException e)
{
e.printStackTrace();
} catch (SecurityException e)
{
e.printStackTrace();
} catch (ClassNotFoundException e)
{
e.printStackTrace();
} catch (IllegalAccessException e)
{
e.printStackTrace();
} catch (IllegalArgumentException e)
{
e.printStackTrace();
} catch (InvocationTargetException e)
{
e.printStackTrace();
}
}
return obj;
}
/**
* 需要返回单个对象信息时,我们用Map存储,如果查询到不止一个对象或者没有查询到对象,返回null;
* @param sql
* @param objects
* @return
*/
private static Map<String,Object> queryForMap(String sql,Object...objects)
{
//新建一个Map,存放结果。key存放从数据库中取出的column名称,value存放相应column取出来的值(用rs.getObject(columnname)方法取出)
//
Map<String,Object> result = new HashMap<String,Object>();
Connection conn = DButil.getConnection(); //建立与数据库的连接
PreparedStatement pStam = null;
ResultSet rs = null;
try
{
pStam = DButil.prepareStatement(conn, sql);
for(int i=0;i<objects.length;i++) //对sql语句里的 ?进行填充
{
pStam.setObject(i+1, objects[i]);
}
rs = pStam.executeQuery(); //拿到查询结果
if(rs.next())
{
ResultSetMetaData rsmd = rs.getMetaData(); //拿到查询结果的字段
int count = rsmd.getColumnCount(); //字段数量
for(int i=0;i<count;i++)
{
result.put(rsmd.getColumnName(i+1), rs.getObject(rsmd.getColumnName(i+1)));
}
if(rs.next())
result = null;
}
} catch (SQLException e)
{
e.printStackTrace();
}finally
{
DButil.closeResultSet(rs);
DButil.closePreparedStatement(pStam);
DButil.closeConnection(conn);
}
return result;
}
/**
* 要返回多个对象时,我们把查询出来的单个对象的信息全部放在一个Map中,然后把这些单个对象的信息全放到
* List中返回
* @param sql
* @param objects
* @return
*/
private static List<Map<String,Object>> queryForMapList(String sql,Object...objects)
{
List<Map<String,Object>> result = new ArrayList<Map<String,Object>>(); //建立一个存放结果的List
Connection conn = DButil.getConnection(); //建立与数据库的连接
PreparedStatement pStam = null;
ResultSet rs = null;
try
{
pStam = DButil.prepareStatement(conn, sql);
for(int i=0;i<objects.length;i++) //对sql语句里的 ?进行填充
{
pStam.setObject(i+1, objects[i]);
}
rs = pStam.executeQuery(); //拿到查询结果
while(rs.next())
{
ResultSetMetaData rsmd = rs.getMetaData(); //拿到查询结果的字段
int count = rsmd.getColumnCount(); //字段数量
Map<String,Object> map = new HashMap<String,Object>(); //一个存放数据的map,key=字段名称,value=字段的内容
for(int i=0;i<count;i++)
{
map.put(rsmd.getColumnName(i+1), rs.getObject(rsmd.getColumnName(i+1)));
}
result.add(map);//将存放一条数据的map放进List
}
} catch (SQLException e)
{
e.printStackTrace();
}finally
{
DButil.closeResultSet(rs);
DButil.closePreparedStatement(pStam);
DButil.closeConnection(conn);
}
return result;
}
}
在Test类中做如下测试
package com.yck.test;
import java.util.List;
import com.yck.bean.User;
import com.yck.database.DataUtil;
public class Test
{
public static void main(String[] args)
{
String sql1 = "select * from t_user where name = ?";
User user = DataUtil.selectForBean(User.class, sql1, "张三");
System.out.println(user);
String sql2 = "select * from t_user";
List<User> list1 = DataUtil.selectForBeanList(User.class, sql2);
System.out.println("第一次查询的结果:"+list1);
String sql3 = "insert into t_user values (null,?,?)";
DataUtil.updata(sql3, "王老五",90);
List<User> list2 = DataUtil.selectForBeanList(User.class, sql2);
System.out.println("增加王老五之后:"+list2);
String sql4 = "update t_user set age=? where name =?";
DataUtil.updata(sql4, 200,"张三");
List<User> list3 = DataUtil.selectForBeanList(User.class, sql2);
System.out.println("把张三的年龄改掉之后:"+list3);
}
}
结果如下所示

数据库结果

忘了贴上上面用到的StringUtil的方法。
package com.yck.database;
import java.util.UUID;
public class StringUtil
{
public static String columnToProperty(String column)
{
//判断column是否为空
if(column.equals(null)||column.equals(""))
return "";
Byte length = (byte) column.length(); //获取字段的长度
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i++) //遍历字符
{
if (column.charAt(i) == '_') //判断字符是否为下划线 _
{
while (column.charAt(i + 1) == '_') //如果是并且下一个还是是下划线,自增一个单位
{
i++;
}
sb.append(("" + column.charAt(++i)).toUpperCase()); //如果是并且下一个不是下划线,下一个字母变为大写
}
else
{
sb.append(column.charAt(i)); //如果不是下划线,直接保存
}
}
return sb.toString();
}
/**
* 把首字母大写
* @param str
* @return
*/
public static String upperCaseFirstCharacter(String str)
{
StringBuilder strBuilder = new StringBuilder();
char[] arr = str.toCharArray();
for(int i=0;i<arr.length;i++)
{
if(i==0)
strBuilder.append((arr[i]+"").toUpperCase());
else strBuilder.append(arr[i]+"");
}
return strBuilder.toString();
}
/**
* 生成32位uuid
* @return
*/
public static String createUniqueid()
{
UUID uniqueid = UUID.randomUUID();
String str = uniqueid.toString();
String uuidStr=str.replace("-", "");
return uuidStr;
}
}
手把手封装数据层之DataUtil数据库操作的封装的更多相关文章
- PHP中对数据库操作的封装
在动态网面设计中很多都要涉及到对数据库的操作,但是有时跟据需要而改用其它后台数据库,就需要大量修改程序.这是一件枯燥.费时而且容易出错的功作.其实我们可以用PHP中的类来实现对数据库操作的封装,从而使 ...
- C# .NET更智能的数据库操作的封装完整版(重构)
前述: 第一次发表文章,不过是对数据库简单的封装,主要是阐述下思路.那么在上篇文章,在大家的指导下和提出意见,并自己对代码进行了思考.在这两天我重构了新的框架,我觉得我写的可以称得上框架,为什么?请大 ...
- C# .NET更智能的数据库操作的封装
前述: 对数据库操作的封装,相信网络上已经有一大堆,ORM框架,或者是.NET本身的EF,都很好的支持数据库操作.这篇文章是分享自己所思考的,对数据库操作的简单封装.我对于这篇文章,认为被浏览者所关注 ...
- 05:ModelForm 数据验证 & 生成html & 数据库操作
目录:Django其他篇 01:Django基础篇 02:Django进阶篇 03:Django数据库操作--->Model 04: Form 验证用户数据 & 生成html 05:Mo ...
- 手把手封装数据层之DButil数据库连接的封装
最近这段时间一直在用SSM框架做增删改查,突然想把以前还不会用框架的时候,综合百度和各种资料结合API文档抄袭而来的数据层的封装分享给大家.这边先封装一个DButil. 我这个封装就是烂大街的那种,没 ...
- android菜鸟学习笔记20----Android数据存储(四))Android数据库操作
Android内置了一个名为SQLite的关系型数据库,这是一款轻量型的数据库,操作十分简便.SQLite与别的数据库不同的是,它没有数据类型.可以保存任何类型的数据到你所想要保存的任何表的任何列中. ...
- django的模型类管理器-----------数据库操作的封装
模型实例方法 str():在将对象转换成字符串时会被调用. save():将模型对象保存到数据表中,ORM框架会转换成对应的insert或update语句. delete():将模型对象从数据表中删除 ...
- Android数据读取之Sqlite数据库操作
咱们书接上文,继续来说说Android数据读取,这回,我们要讲的是Sqlite数据库的相关操作.以一个实例开始吧: 首先,上图,看看做成后的效果: 大概描述:类似于浏览器的收藏夹,网站名称,网站地址, ...
- 常用的PHP函数封装,有排序和数据库操作函数
//二分查找 function bin_sch($array, $low, $high, $k) { if ($low <= $high) { $mid = intval(($low + $hi ...
随机推荐
- Java多线程缓存器简单实现
package com.charles.utils; import java.util.HashMap; import java.util.Map; import java.util.concurre ...
- Struts2简诉
Struts2框架是基于MVC模式的开源,MVC模式是一种开发方式,主要作用是对组件之间进行隔离,M代表业务逻辑层,V代表视图层,C代表控制层.有利于代码的后期维:Struts2框架的源码主要来于We ...
- ASPCMS改造中
10月中旬的时候,芹芹大神给我接了个做网站的活,一番商量过后,我以低得说出来丢人TT的价格接了.主要是想借此摸清网站制作的一条龙服务. 目前根据ASPCMS开源管理系统,做了个大致的构架,下面上草图: ...
- 机器学习(4)Hoeffding Inequality--界定概率边界
问题 假设空间的样本复杂度(sample complexity):随着问题规模的增长导致所需训练样本的增长称为sample complexity. 实际情况中,最有可能限制学习器成功的因素是训练数据的 ...
- angular JS中使用jquery datatable 自定义搜索按钮点击事件 和mRender的 ng-click事件
'use strict'; app.controller('DataTableCtrl', function ($scope, $compile) { $scope.searchFiles = { n ...
- jsp元素
1.指令元素:用于在JSP转换为Servlet阶段提供JSP页面的相关信息,如页面采用的字符编码集.页面中需要导入的类等信息,指令元素不会产生任何的输出到当前JSP的输出流中 指令元素有三种指令:pa ...
- Angular页面加载后自动弹窗
首先在控制器内写好一个弹窗,我用的是ionic的默认提示对话框 // 一个确认对话框 $scope.showConfirm = function() { var confirmPopup = $ion ...
- matlab怎么查看已安装哪些工具箱和…
问题描述:matlab怎么查看已安装哪些工具箱和它们相应的版本 解决方法:在命令行里敲击der,回车 效果:
- 51. leetcode 530. Minimum Absolute Difference in BST
530. Minimum Absolute Difference in BST Given a binary search tree with non-negative values, find th ...
- python 密码学编程
最近在看一本书.名字是 python密码学编程.在此做一些笔记,同时也为有需要的人提供一些参考. *************************************************** ...