JDBC+ 反射实现一个简易的工具类
首先构建一个反射工具类
主要有获取方法和获取字段两个方法
本来是准备再写个获取对应方法的参数名和参数类型的
如下 打印出来的参数名是 arg0>>class java.lang.Long
不是我们想要的 且在1.8后才能获取 所以在下面的getMethod方法使用一个
取巧的方式 且只针对javabean的set方法 显然很 low
Method men = cls.getMethod("setId", Long.class);
Parameter[] parameters = men.getParameters();
for (Parameter parameter : parameters) {
System.out.println(parameter.getName() + ">>" + parameter.getType());
}
public class ReflectClassUtil {
/**
* 获取类中所有字段和对应类型 将字段名做key 类型做value
*
* @param cls
* @return Map
*/
public Map getField(Class cls) {
HashMap<String, Class> map = new HashMap();
Field[] fields = cls.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field fiel = fields[i];
fiel.setAccessible(false);
map.put(fiel.getName(), fiel.getType());
}
return map;
}
/**
* 通过字节码文件对象获取改类的所有方法 用参数名做key值 method做值
*
* @param <T>
* @param cls
* @return Map<String, Method>
*/
public Map getMethods(Class cls) {
Method[] methods = cls.getDeclaredMethods();
Map<String, Method> map = new HashMap<>();
for (Method method : methods) {
method.setAccessible(false);
if (method.getName().startsWith("set")) {
//将方法名截取set 获得后面的字符串 再将首字母大写转为小写即可获得参数名
//显然很low 且大大降低了复用性
char[] ns = method.getName().substring(3).toCharArray();
ns[0] = Character.toLowerCase(ns[0]);
String name = new String(ns);
// System.out.println(name);
map.put(name, method);
}
}
return map;
}
}
在结合jdbc 将查询方法的代码复用性提高
下面类中提供了statement方法 和PreparedStatement方法
查询代码大同小异 其他诸如增加 删除 修改只需简单封装成方法即可调用
import java.io.IOException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class JDBCUtill {
private static JDBCUtill instance;
private static Properties prop = new Properties();
private String url;
private String username;
private String password;
static {
try {
prop.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("jdbc.properties"));
Class.forName(prop.getProperty("driverClassName"));
instance = new JDBCUtill();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 一个简易的封装查询方法
*
* @param cls
* @param sql
* @return
*/
public <T> List<T> qeuryAll(T t, String sql) {
Connection conn = getConnection();
Statement statement = getStatement(conn);
ResultSet rs = getResultSet(statement, sql);
ReflectClassUtil util = new ReflectClassUtil();
Class cls = t.getClass();
ResultSetMetaData metaData = null;
Map methodsmap = util.getMethods(cls);
List<T> list = new ArrayList<>();
try {
Object o = cls.newInstance();
metaData = getResultSetMetaData(rs);
int count = metaData.getColumnCount();
while (rs.next()) {
for (int i = 1; i <= count; i++) {
String name = metaData.getColumnName(i);
Object os = rs.getObject(name);
Method method = (Method) methodsmap.get(name);
method.invoke(o, os);
}
list.add((T) o);
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
/**
* 获取连接对象
*
* @return Connection
*/
public Connection getConnection() {
url = prop.getProperty("url");
username = prop.getProperty("username");
password = prop.getProperty("password");
Connection conn = null;
try {
conn = DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
/**
*
* @param conn
* 连接对象
* @return Statement
*/
public Statement getStatement(Connection conn) {
Statement ps = null;
try {
ps = conn.createStatement();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return ps;
}
/**
*
* @param sql
* 预编译语句
* @param conn
* @param params
* params中的数据要和预编译中插入的数据顺序一致
* @return PreparedStatement
*/
public PreparedStatement getPreparedStatement(String sql, Connection conn, Object[] params) {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
for (int i = 1; i <= params.length; i++) {
ps.setObject(1, params[i - 1]);
}
} catch (SQLException e) {
e.printStackTrace();
}
return ps;
}
/**
*
* @param statement
* @param sql
* 执行语句
* @return ResultSet
*/
public ResultSet getResultSet(Statement statement, String sql) {
ResultSet rs = null;
try {
rs = statement.executeQuery(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return rs;
}
/**
*
* @param rs
* ResultSet
* @return ResultSetMetaData
*/
public ResultSetMetaData getResultSetMetaData(ResultSet rs) {
ResultSetMetaData metaDate = null;
try {
rs.getMetaData();
} catch (SQLException e) {
e.printStackTrace();
}
return metaDate;
}
public static JDBCUtill getInstance() {
return instance;
}
private JDBCUtill() {
}
}
补充:在经过查询之后 发现下面这篇文章解决了java1.8获取参数名为arg0的问题
原文链接:https://www.cnblogs.com/zhangshiwen/p/6022794.html
总结:总的来说 本代码的改进之处还有很多 受限之处颇多
如果以mybatis框架为准的话 可以将sql和javaBean类信息写在XML文件中
然后利用Dom4j解析xml文件获取对应的sql语句
且数据库连接对象Connection可以利用JDBC写一个原生的数据库连接池.
结语:编程路漫漫 永无止境