手把手封装数据层之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 ...
随机推荐
- Objective-C 自定义UISlider滑杆 分段样式
效果 自定义一个功能简单的分段的滑杆 可显示分段名 为了显示效果,我们将滑块和节点都设置为不规则 这里只实现了分段的slider,未分段的没有实现,有兴趣的可以定义另一种类型做个判断修改下 需求分析 ...
- .babelrc 文件
文件干啥用的 babel是降es6转义成浏览器能理解的es5语法. 如果项目中用了babel 转移,需要定义babel需要的插件和预设转码. babel 一般可以配合 webpack . browse ...
- 【性能】web提升性能的小总结
1. 异步加载js文件,判断文件是否已加载,不重复加载 if (typeof echarts === 'undefined') { console.log('异步加载echarts'); $.getS ...
- 阿里云服务器Windows Server 2008/2012部署Office Web Server 2013
以前成功将Office Web Server 2013部署在了本地服务器上,此次是将Office Web Server 2013部署在阿里云服务器Windows Server 2008和2012上,中 ...
- ETL作业自动化调度软件TASKCTL4.5安装程序是选项解释
下文仅针对TASKCTL4.5有效,在执行安装程序后,会看到安装程序有4个选项,其中,1和2是需要了解的. 1, 典型安装: 这个选项是单机部署,在第一次使用TASKCTL的时候,我用的是这种安装方式 ...
- IBM Websphere 集群会话共享问题解决办法
遇到一应用部署环境如下图: 两台HTTP SERVER(以下简称IHS)负责转发数据包,其中F5采用粘性模式,即一个用户在会话周期内的数据包一定会被转发到IHS中的一台, 但IHS 到Web Serv ...
- Hibernate的系统 学习
Hibernate的系统 学习 一.Hibernate的介绍 1.什么是Hibernate? 首先,hibernate是数据持久层的一个轻量级框架.数据持久层的框架有很多比如:iBATIS,myBat ...
- [补档][Poi2010]Monotonicity 2
[Poi2010]Monotonicity 2 题目 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k]. 选出一个长度为L的子序列(不要求连续),要求这个子序列 ...
- 使用VS Code开发.Net Core 2.0 MVC Web应用程序教程之二
好了,废话也不多说,咱们直接来看看这款MVC的造型——你可能会大吼:“这……这特么的都是些什么鬼?” 靠,告诉你吧,我也不知道这都是些什么鬼,反正以前我是没有见过这样的MVC.咦,老纸的config文 ...
- Aspose.Words关于域的应用
#region 通过word域去插入相应的数据 /// <summary> /// 通过word域去进行指定位置替换数据 /// </summary> public void ...