Dao设计模式下的JDBC反射机制实现的更新和查询对象的(手写dbUtils源码)。
涉及到的知识:1.JDBC元数据(ResultSetMetaData)
2.反射机制,泛型
3.preparedStatement
Dao.java
package Les_10_Dao设计模式;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import Les_8_反射机制_JDBC_元数据.ReflectionUtils;
/**
* @author zijian wang
* *Dao: Data Access OBJect
* 功能:访问数据信息的类,包含了对数据的CRUD (create ,read , update ,delete)
* 而不包含任何业务相关的信息,实现功能的模块化更有利于代码的更新。
*/
public class Dao {
// insert ,update ,delete操作都可以包含在其中
public void update(String sql, Object... args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = JDBC_tools.getConnection();
preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
preparedStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBC_tools.close(connection, preparedStatement);
}
}
// 查询一条记录,返回对应的对象
public <T> T get(Class<T> clazz, String sql, Object... args) {
T entity = null;
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = JDBC_tools.getConnection();
preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
ResultSetMetaData rsmd = resultSet.getMetaData();
Map<String, Object> map = new HashMap<String, Object>();
int columnCount = rsmd.getColumnCount();
for (int i = 0; i < columnCount; i++) {
String columnLabel = rsmd.getColumnLabel(i + 1);
Object columnValue = resultSet.getObject(columnLabel);
map.put(columnLabel, columnValue);
}
entity = clazz.newInstance();
for (Map.Entry<String, Object> entry : map.entrySet()) {
String propertyName = entry.getKey();
Object value = entry.getValue();
ReflectionUtils.setFieldValue(entity, propertyName, value);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBC_tools.close(connection, preparedStatement, resultSet);
}
return entity;
}
JDBC_tools.java
package Les_10_Dao设计模式;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBC_tools {
// 获取连接
public static Connection getConnection() {
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useSSL=false";
String user = "root";
String password = "root";
Connection conn = null;
try {
Class.forName(driver);
conn = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
// 关闭连接 和PreparedStatement(任何时候都不要使用 Statement!!!)
public static void close(Connection connection, PreparedStatement preparedStatement) {
if (connection != null) {
try {
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 关闭连接,权限, Resulset
public static void close(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) {
if (connection != null) {
try {
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (resultSet != null) {
try {
resultSet.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 执行sql语句,可以执行任何添加和修改的操作
*
* @param sql:insert
* ,update ,delete 不包含select
* @param args:填写sql占位符的可变参数
*/
public static void update2(String sql, Object... args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = JDBC_tools.getConnection();
preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
preparedStatement.executeUpdate();
System.out.println("更新成功!!");
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBC_tools.close(connection, preparedStatement, null);
}
}
/**
* 执行sql的方法
*
* @param sql:insert
* ,update ,delete 不包含select
* @throws SQLException
*/
public static void update(String sql) throws SQLException {
Connection connection = getConnection();
// 2.准备插入的SQL语句
// 3执行插入操作 (1.获取操作sql语句的Statement 对象 2.
Statement statement = connection.createStatement();
try {
// 调用Statement对象的executeUpdate(sql)执行SQL语句执行插入)
statement.execute(sql);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
/*
* 关闭的顺序是:先关闭后获取的,先关闭Statement 后关闭Connection 关闭的顺序可能是
* 先关闭后获取的,先关闭Statement 后关闭Connection
*/
if (statement != null) {
// 4.关闭Statement对象
statement.close();
}
} catch (Exception e2) {
// 关闭connection对象
connection.close();
}
}
}
}
ReflectionUtils.java
package Les_10_Dao设计模式;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import com.mysql.jdbc.Field;
/**
* 反射的 Utils 函数集合
* 提供访问私有变量, 获取泛型类型 Class, 提取集合中元素属性等 Utils 函数
* @author Administrator
*
*/
public class ReflectionUtils {
/**
* 通过反射, 获得定义 Class 时声明的父类的泛型参数的类型
* 如: public EmployeeDao extends BaseDao<Employee, String>
* @param clazz
* @param index
* @return
*/
@SuppressWarnings("unchecked")
public static Class getSuperClassGenricType(Class clazz, int index) {
Type genType = clazz.getGenericSuperclass();
if (!(genType instanceof ParameterizedType)) {
return Object.class;
}
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
if (index >= params.length || index < 0) {
return Object.class;
}
if (!(params[index] instanceof Class)) {
return Object.class;
}
return (Class) params[index];
}
/**
* 通过反射, 获得 Class 定义中声明的父类的泛型参数类型
* 如: public EmployeeDao extends BaseDao<Employee, String>
* @param <T>
* @param clazz
* @return
*/
@SuppressWarnings("unchecked")
public static <T> Class<T> getSuperGenericType(Class clazz) {
return getSuperClassGenricType(clazz, 0);
}
/**
* 循环向上转型, 获取对象的 DeclaredMethod
* @param object
* @param methodName
* @param parameterTypes
* @return
*/
public static Method getDeclaredMethod(Object object, String methodName, Class<?>[] parameterTypes) {
for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
.getSuperclass()) {
try {
// superClass.getMethod(methodName, parameterTypes);
return superClass.getDeclaredMethod(methodName, parameterTypes);
} catch (NoSuchMethodException e) {
// Method 不在当前类定义, 继续向上转型
}
// ..
}
return null;
}
/**
* 使 filed 变为可访问
* @param field
*/
public static void makeAccessible(java.lang.reflect.Field field) {
if (!Modifier.isPublic(field.getModifiers())) {
field.setAccessible(true);
}
}
/**
* 循环向上转型, 获取对象的 DeclaredField
* @param object
* @param filedName
* @return
*/
public static java.lang.reflect.Field getDeclaredField(Object object, String filedName) {
for (Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass
.getSuperclass()) {
try {
return superClass.getDeclaredField(filedName);
} catch (NoSuchFieldException e) {
// Field 不在当前类定义, 继续向上转型
}
}
return null;
}
/**
* 直接调用对象方法, 而忽略修饰符(private, protected)
* @param object
* @param methodName
* @param parameterTypes
* @param parameters
* @return
* @throws InvocationTargetException
* @throws IllegalArgumentException
*/
public static Object invokeMethod(Object object, String methodName, Class<?>[] parameterTypes, Object[] parameters)
throws InvocationTargetException {
Method method = getDeclaredMethod(object, methodName, parameterTypes);
if (method == null) {
throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + object + "]");
}
method.setAccessible(true);
try {
return method.invoke(object, parameters);
} catch (IllegalAccessException e) {
System.out.println("不可能抛出的异常");
}
return null;
}
/**
* 直接设置对象属性值, 忽略 private/protected 修饰符, 也不经过 setter
* @param object
* @param fieldName
* @param value
*/
public static void setFieldValue(Object object, String fieldName, Object value) {
java.lang.reflect.Field field = getDeclaredField(object, fieldName);
if (field == null)
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
makeAccessible(field);
try {
field.set(object, value);
} catch (IllegalAccessException e) {
System.out.println("不可能抛出的异常");
}
}
/**
* 直接读取对象的属性值, 忽略 private/protected 修饰符, 也不经过 getter
* @param object
* @param fieldName
* @return
*/
public static Object getFieldValue(Object object, String fieldName) {
java.lang.reflect.Field field = getDeclaredField(object, fieldName);
if (field == null)
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
makeAccessible(field);
Object result = null;
try {
result = field.get(object);
} catch (IllegalAccessException e) {
System.out.println("不可能抛出的异常");
}
return result;
}
}
Student.java
public class Student {
private int id;
private String name;
private String grade;
public Student() {
super();
}
public Student(int id, String name, String grade) {
super();
this.id = id;
this.name = name;
this.grade = grade;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGrade() {
return grade;
}
public void setGrade(String grade) {
this.grade = grade;
}
}