利用反射对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() + " = ?, ");
				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稍微改变下可用。

猜你喜欢

转载自blog.csdn.net/qq_44783283/article/details/107067587