lyl890

导航

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();//一定要关闭连接
            }
        }



    }
}

  

posted on 2022-08-16 15:44  静静书中仙  阅读(20)  评论(0编辑  收藏  举报