利用反射对dao层进行重写

    技术2022-07-11  106

    反射写一个通用的dao层

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

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

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

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

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

    如何用反射操作操作

    拼接sql语句拿到表名拿到实体类的字段拿到字段的值

    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() + " = ?, "); else sql.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稍微改变下可用。
    Processed: 0.014, SQL: 9