jdbcUtils
package com.util; import java.lang.reflect.InvocationTargetException; import java.sql.*; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; public class JDBCUtils { static { try { Class.forName("com.mysql.cj.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); System.out.println("驱动加载失败");//写到日志文件中 } } private static final String url = "jdbc:mysql://175.24.163.193:3306/mysql2206?useUnicode=true&characterEncoding=UTF-8&serverTimezone=PRC"; private static final String userName = "root"; private static final String passWord = "Mypass123@"; /** *执行 insert | update| delete语句都可以调用该方法 该方法不支持事务(将来再做支持事务的方法) * 动态代理 ,ThreadLocal * * * @param sql 传入insert | update| delete语句 * @param values 第一个参数的SQL语句中存在N个?号,则values传入?号占位符的值 * 如要执行:sql="update emp set sal=sal+?" 则第二个参数必需传递一个值(传入100) 表示所有员工的工资+100 * 如要执行:sql=" insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno) values(?,?,?,?,?,?,?,?)" * 则第二个参数values传入8个值 分别对应员工号到部门号 values=9999,"Jerry","CLERK",7788,"2022-08-08",199999,100000,10 * * * @return */ public static int update(String sql,Object... values)throws SQLException { Connection connection = null; try { //获得连接 connection = DriverManager.getConnection(url, userName, passWord); PreparedStatement pstmt = connection.prepareStatement(sql); //得到可运行SQL的PreparedStatement对象 //根据values的长度(元素个数)循环调用setObject方法 if(values!=null){ for(int i=0;i<values.length;i++){ //之前是用setInt,setString等方法传入与数据库表字段匹配的java类型 //但调用setObject方法时,只要values中存在元素类型与数据库的类型匹配就可以了。 pstmt.setObject(i+1,values[i]); } } return pstmt.executeUpdate();//执行SQL语句 // }finally { if (connection!=null){ connection.close();//一定要关闭连接 } } } /** * 此方法完成简单的多表查询,单表查询的结果集映射,将结果集每一条数据映射到该方法第二个参数所表示的JavaBean对象中 * 不适用于查询列中出现分组函数(查询结果的列名无法与第二个参数对应的javaBean属性不一致的sql) * @param sql * @param cls * @param values * @param <T> * @return * @throws SQLException */ public static <T> ArrayList<T> queryData(String sql,Class<T> cls, Object... values) throws SQLException, Exception { ArrayList<T> resutlData = new ArrayList<>(); Connection connection = null; try { //获得连接 connection = DriverManager.getConnection(url, userName, passWord); PreparedStatement pstmt = connection.prepareStatement(sql); //得到可运行SQL的PreparedStatement对象 //根据values的长度(元素个数)循环调用setObject方法 if(values!=null){ for(int i=0;i<values.length;i++){ //之前是用setInt,setString等方法传入与数据库表字段匹配的java类型 //但调用setObject方法时,只要values中存在元素类型与数据库的类型匹配就可以了。 pstmt.setObject(i+1,values[i]); } } ResultSet rs = pstmt.executeQuery();//执行SQL语句 ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); while (rs.next()){//取出每一行 //一行数据先放到一个Map对象中 Map<String,Object> rowData = new HashMap<>(); for(int i=1;i<=columnCount;i++){ String columnName = metaData.getColumnLabel(i); String columnTypeName = metaData.getColumnTypeName(i);//获得列的数据类型 int c = metaData.getPrecision(i); int scale = metaData.getScale(i); System.out.println("列的数据类型:"+columnTypeName+"长度:"+c+"小数位数:"+scale); Object columnValue = null; if (columnTypeName.equals("INT")){ columnValue = rs.getInt(i); }else if (columnTypeName.equals("VARCHAR")){ columnValue = rs.getString(i); }else if (columnTypeName.equals("DATE")){ columnValue = rs.getDate(i); }else if (columnTypeName.equals("DATETIME")){ columnValue =rs.getString(i); //rs.getTimestamp(i); }else if (columnTypeName.startsWith("DECIMAL")){ if (scale>0) { columnValue = rs.getDouble(i); }else{ columnValue = rs.getInt(i); } }else if (columnTypeName.equals("CLOB")){ columnValue = rs.getString(i); }else{ columnValue = rs.getObject(columnName);//根据列名取出列值 } rowData.put(columnName,columnValue); } //利用反射技术将一行数据映射一个javaBaen. T javaBean = ReflectUtil.setMapValueToBean(rowData,cls); resutlData.add(javaBean); } return resutlData; }finally { if (connection!=null){ connection.close();//一定要关闭连接 } } } //编写一个通用的查询方法,可以根据传入的SQL语句返回指定一的集合 //如: sql= select * from emp 方法返回值变成ArrayList<EmpBean> //如: sql= select * from dept 方法返回值变成ArrayList<DeptBean> //如: sql = "select * from emp ,dept where emp.deptno=dept.deptno " 方法返回值变成ArrayList<EmpBean> //如: sql = select avg(sal),max(sal),min(sal),deptno from emp gorup deptno 方法返回值变成ArrayList<Map<String,Object>> //封装的思想:把变化的部分做为方法参数传入到方法体中,方法体执行固定的程序逻辑 //分析查询比较麻烦的地方在while循环取数据的方法 // /** *此方法可实现任意的select语句查询,但需要传递RowMapper接口的实现类对象,实现rowMap方法 * 在rowMap方法中根据我们传递的select语句 * 自定义查询结果(将一行数据封装到JavaBean,或Object[]数组,或HashMap等) 由方法的调用者自行决定 * * 此方法的弊端在:每调用一次该方法,第二个参数必需传递RowMapper接口的实现类对象。编程比较麻烦 * * * * * @param sql * @param rowMapper 传入RowMapper接口的实现类, 如果实现类为class EmpRowMapper implements RowMapper<EmpBean>{}, * 则方法的返回值类型ArrayList为ArrayList<EmpBean> * @param values * @param <T> * @return * @throws SQLException */ //Object... values可变参数可以传递 值1,值2,值3表示我们要传递的数据,在方法内部当做数组看待的 //Object... values可变参数可以传传递Object[] 类型的数组,在方法内部将期当做数组数 public static <T> ArrayList<T> queryData(String sql,RowMapper<T> rowMapper, Object... values) throws SQLException { ArrayList<T> resutlData = new ArrayList<>(); Connection connection = null; try { //获得连接 connection = DriverManager.getConnection(url, userName, passWord); PreparedStatement pstmt = connection.prepareStatement(sql); //得到可运行SQL的PreparedStatement对象 //根据values的长度(元素个数)循环调用setObject方法 if(values!=null){ for(int i=0;i<values.length;i++){ //之前是用setInt,setString等方法传入与数据库表字段匹配的java类型 //但调用setObject方法时,只要values中存在元素类型与数据库的类型匹配就可以了。 pstmt.setObject(i+1,values[i]); } } ResultSet rs = pstmt.executeQuery();//执行SQL语句 while (rs.next()){//取出每一行 T rowData = rowMapper.rowMap(rs);//回调。传入的是rowMapper实现类的对象,就会回调实现的类相应方法 resutlData.add(rowData); //传入的 sql语句不同,取数据的代码必然不同?如何处理? .多态. 把取数据代表放到某个类的某个方法中,不同查询语句执行代码不一样? //sql = select * from emp; EmpBean em = new EmpBean() em.setXXX(rs.getXXX)取出emp表的数据放到EmpBean对象中 //sql = select * from Dept; DeptBean d = new DeptBean() d.setXXX(rs.getXXX)取出Dept表的数据放到DeptBean对象中 } return resutlData; }finally { if (connection!=null){ connection.close();//一定要关闭连接 } } } public static ArrayList<Map<String,Object>> queryDataByMap(String sql, Object... values) throws SQLException { ArrayList<Map<String,Object>> queryResult = new ArrayList<>();//用于存储查询结果 Connection connection = null; try { //获得连接 connection = DriverManager.getConnection(url, userName, passWord); PreparedStatement pstmt = connection.prepareStatement(sql); //得到可运行SQL的PreparedStatement对象 //根据values的长度(元素个数)循环调用setObject方法 if(values!=null){ for(int i=0;i<values.length;i++){ //之前是用setInt,setString等方法传入与数据库表字段匹配的java类型 //但调用setObject方法时,只要values中存在元素类型与数据库的类型匹配就可以了。 pstmt.setObject(i+1,values[i]); } } ResultSet rs = pstmt.executeQuery();//执行SQL语句 //得到查询结果中的元数据 ResultSetMetaData metaData = rs.getMetaData(); //得到查询结果中的列名 int columnCount = metaData.getColumnCount(); System.out.println("查询结果列数:"+columnCount); while (rs.next()){//取出每一行 Map<String,Object> rowData = new HashMap<>(); for(int i=1;i<=columnCount;i++){ //取出一行中的每一列 String columnName = metaData.getColumnLabel(i);//列名称() Object value = rs.getObject(columnName);//根据列名称取得列值 rowData.put(columnName,value); } //将rowData (map对象)放到ArrayList中 queryResult.add(rowData); } return queryResult; }finally { if (connection!=null){ connection.close();//一定要关闭连接 } } } /** *执行 select 句都可以调用该方法 * * @param sql 传入insert | update| delete语句 * @param values 第一个参数的SQL语句中存在N个?号,则values传入?号占位符的值 * * * @return 返回ResultSet取出的每一行数据,每一行数据放到一个Object[]数组,多行数据放到ArrayList中 */ @Deprecated public static ArrayList<Object[]> queryData(String sql,Object... values) throws SQLException { ArrayList<Object[]> queryResult = new ArrayList<>();//用于存储查询结果 Connection connection = null; try { //获得连接 connection = DriverManager.getConnection(url, userName, passWord); PreparedStatement pstmt = connection.prepareStatement(sql); //得到可运行SQL的PreparedStatement对象 //根据values的长度(元素个数)循环调用setObject方法 if(values!=null){ for(int i=0;i<values.length;i++){ //之前是用setInt,setString等方法传入与数据库表字段匹配的java类型 //但调用setObject方法时,只要values中存在元素类型与数据库的类型匹配就可以了。 pstmt.setObject(i+1,values[i]); } } ResultSet rs = pstmt.executeQuery();//执行SQL语句 //得到查询结果中的元数据 ResultSetMetaData metaData = rs.getMetaData(); //得到查询结果中的列名 int columnCount = metaData.getColumnCount(); System.out.println("查询结果列数:"+columnCount); while (rs.next()){//取出每一行 //根据coumnCount取出每一行的值 //创建Object[]数组,长度根据columnCount决定 Object[] rowData = new Object[columnCount]; for(int i=1;i<=columnCount;i++){ //取出一行中的每一列 // System.out.print(rs.getObject(i)+"\t" ); rowData[i-1] = rs.getObject(i);//把列中的数据放到数组中 } //将rowData放到ArrayList中 queryResult.add(rowData); } return queryResult; }finally { if (connection!=null){ connection.close();//一定要关闭连接 } } } }