利用反射对dao层进行重写

反射写一个通用的dao层

  • 1. 学了反射,就得学会搞事情
  • 2. 反射写dao具体实现

1. 学了反射,就得学会搞事情

  • 我想怎么对实体类操作,就对实体类操作

  • 想实现通用的dao,要满足的条件:

    1. 实体类名与表名一样
    2. 实体字段名与表字段名一样
    3. 实体类定义的属性顺序与表名字段名顺序一样
    4. 使用dao修改,增加时,实体类的属性都要有赋值,因为根据反射拿到所有属性值,和属性名,来拼接成sql语句滴
  • 如何用反射操作操作

    1. 拼接sql语句
    2. 拿到表名
    3. 拿到实体类的字段
    4. 拿到字段的值

2. 反射写dao具体实现

  • BaseDao 拿到连接和释放资源
package com.lovely.dao;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class BaseDao {static {try {Class.forName("oracle.jdbc.OracleDriver");} catch (ClassNotFoundException e) {e.printStackTrace();}}public static Connection getConn() {Connection conn = null;String url = "jdbc:oracle:thin:@127.0.0.1:1521:orcl";try {conn = DriverManager.getConnection(url, "scott", "scott");} catch (SQLException e) {e.printStackTrace();}return conn;}public static void closeAll(Connection conn, PreparedStatement ps, ResultSet rs) {try {if (rs != null)rs.close();if (ps != null)ps.close();if (conn != null)conn.close();} catch (SQLException e) {e.printStackTrace();}}
}
  • 增删改查万能写法
package com.lovely.dao;import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;public class CommonDao {/*** @param entity 给定一个初始化参数的实体,来做添加操作* @return 返回数据库受影响行数*/public int add(Object entity) {int count = -1;Class<?> c = entity.getClass();StringBuffer sql = new StringBuffer();// insert into tab_name values (seq_student.nextval, ?, ?, ? ...);sql.append("insert into " + c.getSimpleName() + " values (seq_" + c.getSimpleName() + ".nextval");// 拿到实体类私有属性对象的数组Field[] fs = c.getDeclaredFields();Field.setAccessible(fs, true);// 排除主键for (int j = 1; j < fs.length; j++) {sql.append(", ?");}sql.append(")");System.out.println(sql);Connection conn = BaseDao.getConn();PreparedStatement ps = null;try {ps = conn.prepareStatement(sql.toString());// 赋值for (int i = 1; i < fs.length; i++) {ps.setObject(i, fs[i].get(entity));}count = ps.executeUpdate();} catch (SQLException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} finally {BaseDao.closeAll(conn, ps, null);}	return count;}/*** * @param c 描述类的类对象* @return 这张表在数据库里面所有的数据*/public List<Object> queryAll(Class<?> c) {ArrayList<Object> list = new ArrayList<Object>();String sql = "SELECT * FROM " + c.getSimpleName();Connection conn = BaseDao.getConn();PreparedStatement ps = null;ResultSet rs = null;conn = BaseDao.getConn();try {ps = conn.prepareStatement(sql);rs = ps.executeQuery();Field[] fs = c.getDeclaredFields();Field.setAccessible(fs, true);while (rs.next()) {// 创建实体类对象Object entity = c.newInstance();// 为实体类的每个属性赋值for (int i = 0; i < fs.length; i++) {// 取结果集中的值Object value = rs.getObject(fs[i].getName());// oracle 和 Java 中的类型不一样  设置属性值时 可能报错if (fs[i].getType() == Integer.class) {value = rs.getInt(fs[i].getName());} else if (fs[i].getType() == Double.class) {value = rs.getDouble(fs[i].getName());} else if (fs[i].getType() == Timestamp.class) {value = rs.getTimestamp(fs[i].getName());}// Can not set java.sql.Timestamp field com.lovely.entity.Product.pdate to java.sql.Date// 属性是Timstamp类型 Oracle获取的值是 java.sql.Date类型  /*if (fs[i].getType() == Timestamp.class && value.getClass() == java.sql.Date.class) {// 转型java.sql.Date d = (Date) value; value = new Timestamp(d.getTime());}*/// 为实体类属性赋值fs[i].set(entity, value);}list.add(entity);}} catch (SQLException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} finally {BaseDao.closeAll(conn, ps, rs);}return  list;}/*** * @param entity 传入主键即可* @return 返回主键对应的对象*/public Object queryOne(Object entity) {Object obj = null;Class<?> c = entity.getClass();Field[] fs = c.getDeclaredFields();Field.setAccessible(fs, true); // 可访问私有属性String sql = "select * from " + c.getSimpleName() + " where " + fs[0].getName() + " = ?";Connection conn = BaseDao.getConn();PreparedStatement ps = null;ResultSet rs = null;try {ps = conn.prepareStatement(sql);ps.setObject(1, fs[0].get(entity));rs = ps.executeQuery();if (rs.next()) {// 创建当前实体类对象obj = c.newInstance();for (int i = 0; i < fs.length; i++) {// 结果集中每个列的值Object value = rs.getObject(fs[i].getName());// 判断属性值的类型if (fs[i].getType() == Integer.class) {value = rs.getInt(fs[i].getName());} else if (fs[i].getType() == Double.class) {value = rs.getDouble(fs[i].getName());} else if (fs[i].getType() == java.sql.Timestamp.class) {value = rs.getTimestamp(fs[i].getName());}// 为每个属性设置值fs[i].set(obj, value);}}} catch (Exception e) {e.printStackTrace();} finally {BaseDao.closeAll(conn, ps, rs);}return obj;	}/*** * @param entity 要修改的实体对象 实体对象的值都得被初始化* @return 返回受影响行数*/public int update(Object entity) {int count = -1;Class<?> c = entity.getClass();StringBuffer sql = new StringBuffer();// update tab_name set * = ?, * = ?, * = ? ... where primary_key = ?sql.append("update " + c.getSimpleName() + " set ");Field[] fs = c.getDeclaredFields();Field.setAccessible(fs, true);// 拼接列名try {for (int i = 1; i < fs.length; i++) {if (i < fs.length - 1)sql.append(fs[i].getName() + " = ?, ");elsesql.append(fs[i].getName() + " = ? ");}} catch (IllegalArgumentException e) {e.printStackTrace();}// 拼接条件sql.append("where " + fs[0].getName() + " = ?");System.out.println(sql);Connection conn = BaseDao.getConn();PreparedStatement ps = null;try {ps = conn.prepareStatement(sql.toString());// 设置 sql 中参数的值for (int i = 1; i < fs.length; i++) {ps.setObject(i, fs[i].get(entity));}// 设置主键值ps.setObject(fs.length, fs[0].get(entity));count = ps.executeUpdate();} catch (SQLException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} finally {BaseDao.closeAll(conn, ps, null);}return count;}/*** * @param entity 要被删除的对象,传入主键即可* @return 返回受影响行数*/public int delete(Object entity) {int count = -1;Class<?> c = entity.getClass();Field primaryKey = c.getDeclaredFields()[0];primaryKey.setAccessible(true);String sql = "delete from " + c.getSimpleName() + " where " + primaryKey.getName() + " = ?";Connection conn = BaseDao.getConn();PreparedStatement ps = null;try {ps = conn.prepareStatement(sql);ps.setObject(1, primaryKey.get(entity));count = ps.executeUpdate();} catch (SQLException | IllegalArgumentException | IllegalAccessException e) {e.printStackTrace();} finally {BaseDao.closeAll(conn, ps, null);}return count;}}
  • 本代码适用Oracle,mysql,sqlserver稍微改变下可用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/420845.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Replication--查看未分发命令和预估所需时间

当复制有延迟时&#xff0c;我们可以使用复制监视器来查看各订阅的未分发命令书和预估所需时间&#xff0c;如下图&#xff1a; 但是当分发和订阅数比较多的时候&#xff0c;依次查看比较费时&#xff0c;我们可以使用sys.sp_replmonitorsubscriptionpendingcmds来查看&#xf…

1006 换个格式输出整数 (15分)

1006 换个格式输出整数 (15分) 让我们用字母 B 来表示“百”、字母 S 表示“十”&#xff0c;用 12…n 来表示不为零的个位数字 n&#xff08;<10&#xff09;&#xff0c;换个格式来输出任一个不超过 3 位的正整数。例如 234 应该被输出为 BBSSS1234&#xff0c;因为它有 2…

利用反射和xml配置文件手写一个小型的框架

通用的增删改查1. 利用xml配置实体类和数据库表名的映射关系2. 根据xml设计&#xff0c;用正确的数据结构映射类封装好xml信息3. 得到数据库连接前&#xff0c;读取xml信息&#xff0c;用map封装成映射数据4. 写dao时根据反射和map生成sql语句&#xff0c;拿到属性值测试为了解…

DPtoLP/LPtoDP 和 ScreenToClient/ClientToScreen

设备坐标&#xff08;Device Coordinate&#xff09;又称为物理坐标&#xff08;Physical Coordinate&#xff09;&#xff0c;是指输出设备上的坐标。通常将屏幕上的设备坐标称为屏幕坐标。设备坐标用对象距离窗口左上角的水平距离和垂直距离来指定对象的位置&#xff0c;是以…

前端学习(1126):递归求数学题

阶乘1*2*3.....*n <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </he…

1007 素数对猜想 (20分)

1007 素数对猜想 (20分) 让我们定义 ​​ 为&#xff1a;dnpn1−pnd_{n} p_{n1} - p_{n}dn​pn1​−pn​&#xff0c;其中pip_{i}pi​是第iii个素数。显然有d11d_{1} 1d1​1&#xff0c;且对于n>1n>1n>1有dnd_{n}dn​是偶数。“素数对猜想”认为“存在无穷多对相邻且…

Spring工作原理

一、 IoC(Inversion of control): 控制反转1、IoC&#xff1a;概念&#xff1a;控制权由对象本身转向容器&#xff1b;由容器根据配置文件去创建实例并创建各个实例之间的依赖关系核心&#xff1a;bean工厂&#xff1b;在Spring中&#xff0c;bean工厂创建的各个实例称作bean二…

前端学习(1127):递归求数学题2

斐波那契数列 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head>…

注解和反射实现dao层增删改查

注解和反射写dao1. 注解的使用2. 使用注解体现映射关系针对上一篇文章&#xff0c;使用xml映射文件和反射实现dao&#xff0c;提出了扩展功能&#xff0c;利用注解来体现实体类和表的映射关系本文是上一篇文章的扩展使用反射和xml实现dao 1. 注解的使用 什么是注解&#xff1…

1008 数组元素循环右移问题 (20分)

输入样例: 6 2 1 2 3 4 5 6 输出样例: 5 6 1 2 3 4 # -*- coding: utf-8 -*- import mathdef right_shift(lst, m):n len(lst)m m % nfor j in range(math.gcd(m, n)):temp lst[j]i jwhile (i - m) % n > j:lst[i] lst[(i - m) % n]i (i - m) % nlst[i] tempretur…

其它数据类型和Json的转化

1.ResultSet→Json public static String resultSetToJson(ResultSet rs) throws SQLException,JSONException { // json数组 JSONArray array new JSONArray(); // 获取列数 ResultSetMetaData metaData rs.getMetaData(); int columnCount metaData.getColumnCount(…

MVC分层开发模式

MVC 1. 什么是mvc开发模式2. 基于servlet手写mvc框架1. 什么是mvc开发模式 mvc不是一种技术&#xff0c;只是一种开发模式使用分层开发模式能在大型项目中&#xff0c;让开发人员更好的协同工作便于项目的维护和扩展 M: Model 模型层->数据库层->daoV: View 视图层->…

1009 说反话 (20分)

1009 说反话 (20分) 给定一句英语&#xff0c;要求你编写程序&#xff0c;将句中所有单词的顺序颠倒输出。 输入格式&#xff1a; 测试输入包含一个测试用例&#xff0c;在一行内给出总长度不超过 80 的字符串。字符串由若干单词和若干空格组成&#xff0c;其中单词是由英文字…

C#_uploadify_mvc_version

jQuery Uploadify在ASP.NET MVC3中的使用 1、Uploadify简介 Uploadify是基于jQuery的一种上传插件&#xff0c;支持多文件、带进度条显示上传&#xff0c;在项目开发中常被使用。 Uploadify官方网址&#xff1a;http://www.uploadify.com/ 2、ASP.NET MVC3中的使用Uploadify 搭…

1010 一元多项式求导 (25分)

输入样例: 3 4 -5 2 6 1 -2 0 输出样例: 12 3 -10 1 6 0 # -*- coding: utf-8 -*-def get_derivation(lst):length len(lst)idx 0while idx < length:if lst[idx 1] ! 0:lst[idx] * lst[idx 1]lst[idx 1] - 1else:lst[idx] 0idx 2return lstif __name__ __main__…

VS2012 发布网站步骤

VS2012中发布网站的方式与以往有了不同&#xff0c;前面的版本发布如图 而2012点publish的时候弹出框有所不同&#xff0c;这边需要新建一个profile名字随便起&#xff0c;发布的方式有好几种&#xff0c; 当然不同的方式配置不同&#xff0c;用的最多的就是files system了 选择…

python 生成个性二维码

1. 效果 gif 图片二维码 带背景图二维码&#xff08;修改了&#xff09; 2. 依赖库 核心库myqr pip install myqr其它依赖库安装pip install pip install pillow, numpy, imageio3. 核心代码 我这里是F盘下的joy文件夹下面代码改变路径&#xff0c;图片名称参数即可 im…

1011 A+B 和 C (15分)

输入样例&#xff1a; 4 1 2 3 2 3 4 2147483647 0 2147483646 0 -2147483648 -2147483647 输出样例&#xff1a; Case #1: false Case #2: true Case #3: true Case #4: false # -*- coding: utf-8 -*-if __name__ __main__:n eval(input())input_list []for i in range…

SharePoint 2013:解决添加域名后每次都需要登录的问题

在SharePoint 2013中&#xff0c;当我们添加一个域名给SP后&#xff08;添加域名的方法请参考此文&#xff1a;http://www.cnblogs.com/jianyus/archive/2013/08/10/3249461.html &#xff09;&#xff0c;每次用域名访问都需要输入用户名和密码&#xff0c;即使该用户已经正确…

1012 数字分类 (20分)

输入样例 1&#xff1a; 13 1 2 3 4 5 6 7 8 9 10 20 16 18 输出样例 1&#xff1a; 30 11 2 9.7 9 输入样例 2&#xff1a; 8 1 2 4 5 6 7 9 16 输出样例 2&#xff1a; N 11 2 N 9 # -*- coding: utf-8 -*-def class_numbers(nums):arr [0] * 5exists [0] * 5flag1 1…