JDBC(三) JdbcFramework数据框架
搭建数据框架:
导入连接池jar包:
<c3p0-config> <default-config> <!--配置连接池初识的连接数--> <property name="initialPoolSize">10</property> <!--配置最大连接数--> <property name="maxPoolSize">25</property> <!--配置最小连接数--> <property name="minPoolSize">5</property> <!--配置驱动--> <property name="driverClass">com.mysql.jdbc.Driver</property> <!--配置URL--> <property name="jdbcUrl">jdbc:mysql://localhost:3306/geekhome</property> <!--配置连接数据库的用户名--> <property name="user">root</property> <!--配置密码--> <property name="password">tjhilu</property> </default-config> </c3p0-config>
用户类:
public class User { private int userId; private String userName; private String password; public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
用户数据操作类:
public class UserDao { /** * 添加用户 * @param user */ public void add(User user){ JdbcUtil.executeUpdate("insert into users(username,password) values(?,?)", new Object[]{user.getUserName(),user.getPassword()}); } public User findUserByName(String userName){ List<User> list = JdbcUtil.executeQuery("select userId,userName,password from users " + "where userName=?",new Object[]{userName},User.class); if(!list.isEmpty()){ return list.get(0); } return null; } }
员工类:
public class Emp { private String firstName; private double salary; private Date hireDate; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public Date getHireDate() { return hireDate; } public void setHireDate(Date hireDate) { this.hireDate = hireDate; } }
数据访问辅助类,封装数据连接与关闭:
/** * 数据访问辅助类,封装数据连接与关闭 */ public class JdbcHandler { //数据池:用dataSource进行接收,是为了以后更换数据池类型 private static DataSource dataSource; static{ //初始化数据池 dataSource = new ComboPooledDataSource(); } /** * 打开数据库连接 * @return */ public static Connection openConnection(){ Connection con = null; if(dataSource != null){ try { con = dataSource.getConnection(); } catch (SQLException e) { e.printStackTrace(); } } return con; } /** * 关闭数据库对象 * @param con * @param pstmt * @param rs */ public static void close(Connection con, PreparedStatement pstmt, ResultSet rs){ try { if(rs != null){ rs.close(); } if(pstmt != null){ pstmt.close(); } if(con != null){ con.close(); } } catch (SQLException e) { e.printStackTrace(); } } }
方便获取结果集的一些数据:
获取结果集的列名称、根据列的名称查找属性、将属性的首字母转换大写
public class JdbcCommonUtil { /** * 获取结果集的列名称 * @param metaData * @return 将列的名称封装成一个String集合,返回出去 */ public static String[] getColumnNames(ResultSetMetaData metaData){ String[] array = null; try { //根据列的数量创建数组 array = new String[metaData.getColumnCount()]; for(int i = 0; i < array.length; i++){ //获取数据列的原名称 FIRST_NAME //array[i] = metaData.getColumnName(i+1); //获取数据列的标签名,标签名会随着别名进行更改,会将最终的名称改为as的别名firstname array[i] = metaData.getColumnLabel(i+1); } } catch (SQLException e) { e.printStackTrace(); } return array; } /** * 根据列的名称查找属性 * @param columnName * @param fields * @return */ public static Field findField(String columnName,Field[] fields){ for (Field field : fields) { //判断属性名称是否相同:对属性名进行遍历,与传入的列名进行比较,如果一致,返回这个属性 if(field.getName().equalsIgnoreCase(columnName)){ return field; } } return null; } /** * 将属性的首字母转换大写 * @param fieldName * @return */ public static String parseUpperField(String fieldName){ return (char)(fieldName.charAt(0)-32)+fieldName.substring(1); } }
数据库访问工具类,封装了数据常用的增删改查的操作方法:
/** * 数据库访问工具类,封装了数据常用的增删改查的操作方法 */ public class JdbcUtil { /** * 用于处理数据增删改 * @param sql 执行的SQL语句 * @param params 注入至SQL语句占位符的值(参数不是必须的) * @return */ public static int executeUpdate(String sql,Object[] params){ int resultCount = -1; Connection con = JdbcHandler.openConnection(); PreparedStatement pstmt = null; if(con != null){ try { pstmt = con.prepareStatement(sql); //判断是否需要注入参数 if(params != null){ //注入参数 for(int i = 0; i < params.length; i++){ //判断每个参数的类型
//可以直接用Object就不用判断每个参数的class类型了 Object param = params[i]; // if(param.getClass() == Integer.class || param.getClass() == int.class){ // pstmt.setInt(i+1, (int)param); // } // else if(param.getClass() == Float.class || param.getClass() == float.class){ // pstmt.setFloat(i+1, (float)param); // } // else if(param.getClass() == String.class){ // pstmt.setString(i+1, param.toString()); // } pstmt.setObject(i+1, param); } } //执行SQL语句:要在if外面进行执行,因为参数可能为null resultCount = pstmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { //关闭数据库:不管try里面的结果如何,都要关闭数据库连接 JdbcHandler.close(con, pstmt, null); } } return resultCount; } /** * 查询行 * @param sql * @param params * @param objClass 数据表映射类的Class * @return */ public static <T> List<T> executeQuery(String sql,Object[] params,Class<T> objClass){ List<T> list = new ArrayList(); //获取连接 Connection con = JdbcHandler.openConnection(); PreparedStatement pstmt = null; ResultSet rs = null; if(con != null){ try { //创建预处理器 pstmt = con.prepareStatement(sql); //判断参数是否存在 if(params != null){ //注入参数 for(int i = 0; i < params.length; i++){ pstmt.setObject(i+1, params[i]); } } //执行查询,获得结果集 rs = pstmt.executeQuery(); //获取结果集的元数据 ResultSetMetaData metaData = rs.getMetaData(); //反射获取对象的所有属性:要调用declareFields才能将私有的属性也获取出来 Field[] fields = objClass.getDeclaredFields(); //解析结果集的数据结构,获得结果集的列名 String[] columnNames = JdbcCommonUtil.getColumnNames(metaData); //迭代结果集 while(rs.next()){ //将实体类实例化:通过无参构造方法创建对象 T t = objClass.newInstance(); //获取每列的值
//遍历通说结果集获取的列名,将列名与属性名进行比较,如果查找到有相对应的属性则将列值赋给属性 for (String columnName : columnNames) { //System.out.println("列名:"+columnName); //根据列名查找属性:传入当前遍历的列名和属性名集合 Field field = JdbcCommonUtil.findField(columnName,fields); if(field != null){ //获取属性的类型 Class fieldClass = field.getType(); //声明列值 Object value = null; //根据属性类型调用结果集中对应的get方法 if(fieldClass == String.class){ value = rs.getString(columnName); } else if(fieldClass == double.class || fieldClass == Double.class){ value = rs.getDouble(columnName); } else if(fieldClass == float.class || fieldClass == Float.class){ value = rs.getFloat(columnName); } else if(fieldClass == int.class || fieldClass == Integer.class){ value = rs.getInt(columnName); } else if(fieldClass == Date.class){ value = rs.getTimestamp(columnName); } //System.out.println(value); //查找相应的setter方法(通过setter方法的名称进行查找setter方法,直接将列值写入),将列值写入 // System.out.println("属性名:"+field.getName()); // System.out.println("set"+JdbcCommonUtil.parseUpperField(field.getName())); Method method = objClass.getMethod("set"+JdbcCommonUtil.parseUpperField(field.getName()),fieldClass); //执行setter方法:invoke第一个参数是调用方法的对象是哪个对象,第二个参数是要传入的值 method.invoke(t,value); } else{ //未找到属性抛出异常:抛出自定义异常 throw new MappingFieldNotFoundException(); } } //System.out.println("---------------------------"); //将实体对象添加至集合 list.add(t); } } catch (SQLException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchMethodException e){ e.printStackTrace(); } catch(InvocationTargetException e){ e.printStackTrace(); } } //关闭数据库 return list; } }
自定义异常:
/** * 映射属性未找到异常 */ public class MappingFieldNotFoundException extends RuntimeException { //如果没有找到相对应的属性和列名,则抛出异常 public MappingFieldNotFoundException() { super("映射的属性未找到!"); } }
测试类:
package com.igeek.test; import com.igeek.dao.UserDao; public class Test { public static void main(String[] args) { //测试修改信息的方法 JdbcUtil.executeUpdate("update users set password=?", new Object[]{"111"}); JdbcUtil.executeUpdate("delete from users where userid=108", null); JdbcUtil.executeUpdate("update users set " + "birthday=? where userid=?", new Object[]{new Date(),2});
//测试查询信息的方法 List<User> list = JdbcUtil.executeQuery("select userid,username,password from users", null, User.class);
//循环打印查找的结果 for (User user : list) { System.out.println(user.getUserId()+"\t"+user.getUserName()+"\t"+user.getPassword()); } //测试查询信息的方法:列名和属性名称不一致时,用as修改列名方便和属性名进行匹配 List<Emp> list = JdbcUtil.executeQuery("select first_name as firstname,salary,hire_date as hireDate " + "from emp where department_id=?", new Object[]{50}, Emp.class); for (Emp emp : list) { System.out.println(emp.getFirstName()+"\t"+emp.getSalary()+"\t"+emp.getHireDate()); }
//通过用户操作类进行查询单行数据 UserDao userDao = new UserDao();
//新建一个用户 User user = new User(); user.setUserName("testName"); user.setPassword("000"); userDao.add(user); //测试查询单行数据 User user = userDao.findUserByName("testName"); if(user != null){ System.out.println(user.getUserId()+"\t"+user.getPassword()); } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!