反射写一个通用的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稍微改变下可用。