JDBC11 - 封装BaseDao
高级应用层封装 BaseDao
基本每个数据表都应该有一个对应的 DAO 接口及其实现类,发现对所有表的操作(增、删、改、查)代码重复度很高,所以可以抽取公共代码,给这些 DAO 的实现类可以抽取一个公共的父类,称为 BaseDao
CRUD分为 DQL 和 非DQL,因此只需封装两个方法
封装 非DQL 返回值固定为int 比较简单
/**
* 封装简化非DQL语句 -- 返回值固定为int
* @param sql 带占位符的SQL语句结构
* @param params 占位符的值作为可变参数传入
* @return
*/
public int executeUpdate(String sql, Object... params) throws Exception {
//获取连接
Connection connection = JDBCUtilsV2.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//可变参可以作为数组使用
for (int i = 1; i <= params.length; i++) {
preparedStatement.setObject(i,params[i-1]);
}
int rows = preparedStatement.executeUpdate();
preparedStatement.close();
//是否回收连接要考虑是否为事务操作
//如果开启事务了 不要管连接 --> 交给业务层处理
//如果没有开启事务,正常回收连接
if (connection.getAutoCommit()) {
//true 没有开启
JDBCUtilsV2.freeConnection();
}
return rows;
}
封装 DQL
- DQL语句封装方法 -> 返回值是什么类型的?
- List
list -> 实体类集合 -> 泛型
- List
- 并不是List
- 数据库数据 -> java的实体类
- table User
- id id
- account account
- password password
- nickname nickname
- 表中一行 -> java类的一个对象 -> 多行 -> List<Java实体类>
- 1.泛型
具体类型通过参数传入 - 2.使用反射机制,实现属性赋值
- 1.泛型
- public
List executeQuery(Class clazz, String sql, Object...params);
/**
* 将查询结果封装到一个实体集合
* @param clazz 要接值的实体类集合的模板对象
* @param sql 查询语句,要求列名或别名等于实体类的属性名 u_id as uId => uId
* @param params 占位符的值,要和?位置对应传递
* @return 查询的实体类集合
* @param <T> 声明结果的类型
* @throws Exception
*/
public <T> List<T> executeQuery(Class<T> clazz, String sql, Object... params) throws Exception{
Connection connection = JDBCUtilsV2.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(sql);
if (params != null && params.length != 0) {
for (int i = 1; i < params.length; i++) {
preparedStatement.setObject(i, params[i - 1]);
}
}
ResultSet resultSet = preparedStatement.executeQuery();
List<T> list = new ArrayList<>();
//自动遍历列
//获取列的信息对象
//TODO metaData对象 装的当前结果集中列的信息对象(可以获取列的数量、列的名称)
ResultSetMetaData metaData = resultSet.getMetaData();
//知道列数后,就可以通过下标水平遍历列
int columnCount = metaData.getColumnCount();
while (resultSet.next()) {
//一行数据 对应一个 T类型的对象
//通过反射实例化对象 -- 调用类的无参构造函数实例化对象
T t = clazz.newInstance();
for (int i = 1; i <= columnCount; i++) {
//对象的属性值
Object value = resultSet.getObject(i);
//对象的属性名
String propertyName = metaData.getColumnLabel(i);
//反射 给对象属性值赋值
Field field = clazz.getDeclaredField(propertyName);
field.setAccessible(true); //属性可以设置,打破private的修饰限制
//参数1 要赋值的对象 参数2 具体的属性值
field.set(t, value);
}
list.add(t);
}
//关闭资源
resultSet.close();
preparedStatement.close();
if (connection.getAutoCommit()) {
//true 没有开启事务,可以直接关闭
JDBCUtilsV2.freeConnection();
}
return list;
}
封装之后使用
public class PSCRUDPart extends BaseDao {
@Test
public void testInsert() throws Exception {
String sql = "insert into t_user(account,password,nickname) values(?,?,?);";
int rows = executeUpdate(sql, "test", "123123", "test");
System.out.println("影响行数 = " + rows);
}
@Test
public void testUpdate() throws Exception {
String sql = "update t_user set nickname =? where id =?;";
int rows = executeUpdate(sql, "new_name", "1");
System.out.println("影响行数 = " + rows);
}
@Test
public void testDelete() throws ClassNotFoundException, SQLException {
String sql = "delete from t_user where id = ?;";
int rows = executeUpdate(sql, "2");
System.out.println("影响行数 = " + rows);
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析