首先了解下BaseDao的字面意思
Base:基本的
Dao:Data Access Object 数据访问对象,也称为数据访问层
使用BaseDao的好处:我们在初学java的JDBC的部分我们应该是经常会写对数据的增删改查,比如说对学生的增删改查,或者是老师的增删改查等等。。。然而这时你会发现你所写的很多代码都是重复的,这时你就会考虑到代码的优化问题,以及常提到的高内聚低耦合这个概念。
接下来就是常用的代码部分:
我们在写增删改的时候会发现增删改这三种的代码几乎是相同的,不同的就是sql语句,所以就先把简单的展示出来:
/**
* 实现不同表的增删改
*/
protected void update(String sql, Object... args) throws SQLException {
// 获取连接 相同
Connection conn = ProxyUtil.conn;
// 准备sql 不同
// PreparedStatement 相同
PreparedStatement ps = conn.prepareStatement(sql);
// 填充占位符 相似
for (int i = 0; i < args.length; i++) {
ps.setObject((i + 1), args[i]);
}
// 执行sql 相同
ps.executeUpdate();
ps.close();
}
相对而言,我们要实现的查询要复杂一点,要考虑的有点多,下面展示查询的代码:
/**
* 实现不同表的查询
*
* @throws SQLException
*/
protected List<T> getAll(String sql, Object... args) throws SQLException {
List<T> ts = new ArrayList<>();
// 获取连接 相同
Connection conn = ProxyUtil.conn;
// 准备sql 不同
// PreparedStatement
PreparedStatement ps = conn.prepareStatement(sql);
// 填充占位符 相似
for (int i = 0; i < args.length; i++) {
ps.setObject((i + 1), args[i]);
}
// 执行sql 相同
ResultSet rs = ps.executeQuery();
// 获取元数据
ResultSetMetaData rsmd = rs.getMetaData();
// 通过元数据获取列的数量
int columnCount = rsmd.getColumnCount();
// 处理结果集 相似
while (rs.next()) {
T t = null;
// 获取带泛型的父类
Type genericSuperclass = this.getClass().getGenericSuperclass();
// 强转为带泛型的父类类型
ParameterizedType pt = (ParameterizedType) genericSuperclass;
// 取出泛型
Type[] actualTypeArguments = pt.getActualTypeArguments();
// 取出第0个泛型
Type type = actualTypeArguments[0];
// 泛型的类型
Class c = (Class) type;
// 创建对象
try {
t = (T) c.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// 取出所有的字段
Field[] fields = c.getDeclaredFields();
// 遍历列
for (int i = 1; i <= columnCount; i++) {
// 取出列的值
Object value = rs.getObject(i);
// 取出当前列的名字,表的字段名
String columnLabel = rsmd.getColumnLabel(i);
// set属性值
Field f = null;
a: for (Field field : fields) {
// 类中字段名
String fieldName = field.getName();
// 找到列名和类中的字段名相同的字段
if (columnLabel.equalsIgnoreCase(fieldName)) {
f = field;
break a;
}
}
if (f != null) {
// 改为可以修改
f.setAccessible(true);
try {
if (value instanceof Date) {
f.set(t, ((Date) value).toLocalDate());
} else {
f.set(t, value);
}
} catch (IllegalArgumentException e) {
// 获取field的类型
Class<?> fieldClass = f.getType();
try {
// 创建对象,可能是teacher
Object fieldValue = fieldClass.newInstance();
// 取出fieldClass类中的id字段
Field fieldClassIdField = fieldClass.getDeclaredField("id");
// 把value赋给上一步获取的id字段
fieldClassIdField.setAccessible(true);
fieldClassIdField.set(fieldValue, value);
// 把fieldValue赋给f字段
f.set(t, fieldValue);
} catch (InstantiationException | IllegalAccessException | NoSuchFieldException
| SecurityException | IllegalArgumentException e1) {
e1.printStackTrace();
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
ts.add(t);
}
// 关闭连接
ps.close();
rs.close();
return ts;
}
查询的代码量看着是有点吓人,但是自己能够懂每一步是要实现什么就行了。其实关于关闭连接这个也是可以在写一个通用的方法,就又可以减少代码量了。每一条代码都有一些关键的注释,如果说不理解的也可以直接搜
这里我们实现的查询是一个集合,一般来说我们要查询的数据都是比较多的,查一条的比较少。在这里呢,查询一条指定的数据的代码就不展示了,说说思路吧,查询一条也就是返回的不是集合,应该是一个对象,然后其他的代码基本上是相似的,就把集合改改就是了。
有了BaseDao之后呢,就可以结合数据库中的事务去实现一些功能,有关事务的理解下次再给小伙伴们讲解