现在都是用框架去开发,既简单又快速,给我们提供了很多便利;有利便有弊,坏处就是依赖框架,忘记了Java基础,不在关注底层是怎么实现的,这里大家一起回顾一下最原始的jdbc写法:
第一步:导入jar包,这里不多说了,百度都有;
第二步:创建BaseDao(偷下懒,把所有方法都写在一个类里面了),上代码:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 公共dao类
*/
@Component
public class BaseDao {
private final Logger logger = LoggerFactory.getLogger(BaseDao.class);
private Connection conn = null;
private PreparedStatement ps = null;
private ResultSet rs = null;
/**
* 建立数据库连接
* @return
*/
private Connection getConnection() {
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "123456");
if (!conn.isClosed()) {
logger.info("################# 数据库连接成功 #################");
}
} catch (ClassNotFoundException e) {
logger.error("加载jdbc.Driver异常", e);
throw new RuntimeException("加载jdbc.Driver异常", e);
} catch (SQLException e) {
logger.error("建立数据库连接异常", e);
throw new RuntimeException("建立数据库连接异常", e);
}
return conn;
}
/**
* 方法用途: 公共查询方法,返回List集合
* 操作步骤: TODO
* ${tags}
*/
public List> queryList(Class clazz, String sql, Object... params) {
T t;
List list = new ArrayList<>();
logger.info(sql);
logger.info(null == params? "" : params.toString());
try {
Field[] fields = getAllFields(clazz);
conn = getConnection();
ps = conn.prepareStatement(sql);
initParams(ps, params);
rs = ps.executeQuery();
// 返回结果集
while (rs.next()) {
t = getObjResult(fields, rs, clazz);
list.add(t);
}
logger.info(String.format("################# 查询成功,共%s条记录 #################", list.size()));
} catch (SQLException e) {
logger.error("执行查询异常", e);
throw new RuntimeException("执行查询异常", e);
} finally {
// 关闭数据库连接
closeDb(rs, ps, conn);
}
return list;
}
/**
* 将每行结果存入map集合,对象属性名为key,查询出的结果为value
* @param fields
* @param rs
* @return
*/
private T getObjResult(Field[] fields, ResultSet rs, Class clazz) {
T t = null;
Field field;
Method method;
String fieldName;
String fieldType;
try {
t = clazz.newInstance();
for (int i = 0; i < fields.length; i++) {
field = fields[i];
field.setAccessible(true);
fieldName = field.getName();
if (fieldName.equals("serialVersionUID")) {
continue;
}
fieldType = field.getType().getName();
method = getMethod(clazz, field, fieldName, fieldType);
Object value = rs.getObject(initField(fieldName));
if (fieldType.equals("java.lang.String")) {
method.invoke(t, value);
} else if (fieldType.equals("java.lang.Integer")) {
method.invoke(t, Integer.valueOf(value.toString()));
}
}
} catch (SQLException e) {
logger.error("rs获取结果异常", e);
throw new RuntimeException("rs获取结果异常", e);
} catch (InvocationTargetException e) {
logger.error("method.invoke方法执行异常", e);
throw new RuntimeException("method.invoke方法执行异常", e);
} catch (IllegalAccessException e) {
logger.error("method.invoke方法执行异常", e);
throw new RuntimeException("method.invoke方法执行异常", e);
} catch (InstantiationException e) {
logger.error("建立T对象异常", e);
throw new RuntimeException("建立T对象异常", e);
}
return t;
}
/**
* 对象属性的set方法
* @param clazz
* @param field
* @param fieldName
* @param fieldType
* @return
*/
private Method getMethod(Class clazz, Field field, String fieldName, String fieldType){
Method method = null;
try {
if (fieldType.equals("java.lang.Boolean")) {
method = clazz.getDeclaredMethod("is" + getMethodName(fieldName), field.getType());
} else {
method = clazz.getDeclaredMethod("set" + getMethodName(fieldName), field.getType());
}
} catch (NoSuchMethodException e) {
Class superClazz = clazz.getSuperclass();
method = getMethod(superClazz, field, fieldName, fieldType);
}
return method;
}
/**
* 获取所有属性(getSuperclass:获取父类属性)
* @param clazz
* @param
* @return
*/
private Field[] getAllFields(Class clazz) {
Class superClazz = clazz;
List fieldList = new ArrayList<>();
while (null != superClazz) {
fieldList.addAll(new ArrayList<>(Arrays.asList(superClazz.getDeclaredFields())));
superClazz = superClazz.getSuperclass();
}
Field[] fields = new Field[fieldList.size()];
fieldList.toArray(fields);
return fields;
}
/**
* 将驼峰属性名转换为带下划线字段(xx_xx)
* @param field
* @return
*/
private String initField(String field) {
StringBuilder newField = new StringBuilder();
for (int i = 0; i < field.length(); i++) {
char c = field.charAt(i);
if (Character.isUpperCase(c)) {
newField.append("_").append(Character.toLowerCase(c));
} else {
newField.append(c);
}
}
return newField.toString();
}
/**
* 组装参数
* @param ps
* @param params
*/
private void initParams(PreparedStatement ps, Object... params) {
if (null != params && params.length > 0) {
try {
for (int i = 0; i < params.length; i++) {
ps.setString(i, params[i].toString());
}
} catch (SQLException e) {
logger.error("ps设置参数异常", e);
throw new RuntimeException("ps设置参数异常", e);
}
}
}
/**
* 方法用途: 把一个字符串的第一个字母大写、效率是最高的
* 操作步骤: TODO
* ${tags}
*/
private static String getMethodName(String fildeName) {
byte[] items = fildeName.getBytes();
items[0] = (byte) ((char) items[0] - 'a' + 'A');
return new String(items);
}
/**
* 关闭数据库连接
* @param rs
* @param ps
* @param conn
*/
private void closeDb(ResultSet rs, PreparedStatement ps, Connection conn) {
try {
if (null != rs) {
rs.close();
}
if (null != ps) {
ps.close();
}
if (null != conn) {
conn.close();
}
logger.info("################# 连接关闭成功 #################");
} catch (SQLException e) {
logger.error("关闭连接异常", e);
throw new RuntimeException("关闭连接异常", e);
}
}
}
好了,都是我手敲出来的代码,注释也都加上了,不懂的多读几遍代码吧,实在看不明白先回顾下Java反射的基础(Java反射基础案例)