JDBC中批处理及通过反射处理结果集

10 篇文章 0 订阅


JDBC中的批处理

  • 批处理:
    即批量处理,通过对数据库的一次调用提交相关的SQL语句

  • 作用:
    一次向数据库发送多个SQL语句,可以减少连接数据库的开销,提高性能


以teacher表为例

在这里插入图片描述

Statement批处理

步骤:

序号使用方法描述
1createStatement()创建Statement对象
2setAutoCommit()将auto-commit设置为false
3addBatch()在创建的语句对象上添加SQL语句到批处理中
4executeBatch在创建的语句对象上使用该方法执行所有SQL语句
5commit()提交所有更改

代码示例:

	public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        try {
            //1加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2获得链接
            String userName = "root";
            String passWord = "123456";
            String url = "jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT";
            connection = DriverManager.getConnection(url, userName, passWord);
            connection.setAutoCommit(false);//关闭自动提交事务
            //3定义sql,创建状态通道(进行sql语句的发送)
            statement = connection.createStatement();
            //4定义sql
            String sql1 = "insert into teacher(tname) values('张三1')";
            statement.addBatch(sql1);
            String sql2 = "insert into teacher(tname) values('张三2')";
            statement.addBatch(sql2);
            String sql3 = "insert into teacher(tname) values('张三3')";
            statement.addBatch(sql3);
            String sql4 = "insert into teacher(tname) values('张三4')";
            statement.addBatch(sql4);
            String sql5 = "insert into teacher(tname) values('张三5')";
            statement.addBatch(sql5);
            int[] ints = statement.executeBatch();//执行所有SQL语句
            connection.commit();//手动提交事务
            for (int anInt : ints) {
                System.out.println("anInt = "+anInt);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            try {
                connection.rollback();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            try {
                //5关闭资源
                if(statement != null){
                    statement.close();
                }
                if(connection != null){
                    connection.close();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        } 

运行结果以及sql数据变化:
在这里插入图片描述


PreparedStatement批处理

步骤:

序号使用方法描述
1使用占位符创建SQL语句
2prepareStatement()创建PrepareStatement对象
3setAutoCommit()将auto-commit设置为false
4addBatch()在创建的语句对象上添加SQL语句到批处理中
5executeBatch()在创建的语句对象上使用该方法执行所有SQL语句
6commit()提交所有更改

代码示例:

	public static void main(String[] args) {
        Connection connection = null;
        PreparedStatement pps = null;
        try {
            //1加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2获得链接
            String userName = "root";
            String passWord = "123456";
            String url = "jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT";
            connection = DriverManager.getConnection(url, userName, passWord);
            connection.setAutoCommit(false);//关闭自动提交事务
            //3定义sql,创建状态通道(进行sql语句的发送)
            pps = connection.prepareStatement("insert into teacher(tname) values(?)");
            //4赋值
            pps.setString(1,"李四1");
            pps.addBatch();
            pps.setString(1,"李四2");
            pps.addBatch();
            pps.setString(1,"李四3");
            pps.addBatch();
            pps.setString(1,"李四4");
            pps.addBatch();
            pps.setString(1,"李四5");
            pps.addBatch();
            int[] ints = pps.executeBatch();//执行所有SQL语句
            connection.commit();//手动提交事务
            for (int anInt : ints) {
                System.out.println("anInt = "+anInt);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            try {
                connection.rollback();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            try {
                //5关闭资源
                if(pps != null){
                    pps.close();
                }
                if(connection != null){
                    connection.close();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }//end finally
    }//end main

运行结果以及sql数据变化:

在这里插入图片描述


通过反射处理结果集

以学生表student为例
在这里插入图片描述

根据sql创建对应的类Student:

类名=表名
列名=属性名

public class Student {
    private int stuid;
    private String stuname;
    private int teacherid;

    public int getStuId() {
        return stuid;
    }
    public void setStuId(int stuid) {
        this.stuid = stuid;
    }
    public String getStuName() {
        return stuname;
    }
    public void setStuName(String stuname) {
        this.stuname = stuname;
    }

    public int getTeacherid() {
        return teacherid;
    }

    public void setTeacherid(int teacherid) {
        this.teacherid = teacherid;
    }
}

新建数据处理的接口Dao,定义抽象操作方法:

public interface Dao {
    //定义操作方法
    //查询全部学生,非反射处理
    List<Student> getAllStudent();
}

DaoImplements类实现Dao接口,编写具体方法:

    @Override
    public List<Student> getAllStudent() {
        Connection connection = null;
        PreparedStatement pps = null;
        ResultSet resultSet = null;
        try {
            //1加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2获得链接
            String userName = "root";
            String passWord = "123456";
            String url = "jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT";
            connection = DriverManager.getConnection(url, userName, passWord);
            //3定义sql,创建预状态通道(进行sql语句的发送)
            String sql = "select * from student ";
            pps = connection.prepareStatement(sql);
            //执行sql
            resultSet = pps.executeQuery();
            List<Student> students = new ArrayList<>();//创建学生集合

            //取值
            while(resultSet.next()){
                Student student = new Student();
                student.setStuId(resultSet.getInt("stuid"));
                student.setStuName(resultSet.getString("stuname"));
                student.setTeacherid(resultSet.getInt("teacherid"));
                students.add(student);
            }

            return students;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            try {
                //5关闭资源
                if(resultSet != null){
                    resultSet.close();
                }
                if(pps != null){
                    pps.close();
                }
                if(connection != null){
                    connection.close();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }//end finally
        return null;
    }

编写操作实现类Test:

public class Test{
    public static void main(String[] args) {
        List<Student> allStudent =dao.getAllStudent();
        for (Student student : allStudent) {
            System.out.println(student.getStuId()+","+student.getStuName()+","+student.getTeacherid());
        }
    }
}

输出结果:

1,张三,3
2,李四,1
3,王五,3
4,赵六,1
5,花花,1
6,潇潇,2

实际开发过程中,当表的列很多时,上述写法获取列效率低,通过反射能够简化结果集的处理

还是以student表为例

在数据处理的接口Dao,定义抽象操作方法:

public interface Dao {
    //定义操作方法
    /*
    //查询全部学生,非反射处理
    List<Student> getAllStudent();
    */
    
    //查询全部学生,反射处理
    List<Student> getAllStudent(Class cla);
}

在实现TeacherDao接口的DaoImplements类中,编写具体方法:

    @Override
    public List<Student> getAllStudent(Class cla) {
        Connection connection = null;
        PreparedStatement pps = null;
        ResultSet resultSet = null;
        try {
            //1加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            //2获得链接
            String userName = "root";
            String passWord = "123456";
            String url = "jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT";
            connection = DriverManager.getConnection(url, userName, passWord);
            //3定义sql,创建预状态通道(进行sql语句的发送)
            String sql = "select * from student ";
            pps = connection.prepareStatement(sql);
            //执行sql
            resultSet = pps.executeQuery();
            List students = new ArrayList();//创建学生集合

			/*
			//取值
            while(resultSet.next()){
                Student student = new Student();
                student.setStuId(resultSet.getInt("stuid"));
                student.setStuName(resultSet.getString("stuname"));
                student.setTeacherid(resultSet.getInt("teacherid"));
                students.add(student);
            }
			*/




            //!!!!!!!以下通过反射,让结果集自动匹配set方法

            //得到当前数据库查询结果的列信息
            ResultSetMetaData metaData = resultSet.getMetaData();//存储结果集信息
            int columnCount = metaData.getColumnCount();//得到列数
            String[] columnNames = new String[columnCount];//数组长度为列的数量
            //获取列名
            for(int i = 0;i < columnCount;i++){
                columnNames[i] = metaData.getColumnName(i+1);//列从1开始
                System.out.println("columnName = "+columnNames[i]);
            }
            //获取类中所有的方法
            Method[] declaredMethods = cla.getDeclaredMethods();
            //取值
            while(resultSet.next()){
                try {
                    Object stu = cla.newInstance();//得到一个学生对象
                    //从对应列取出值,赋给对应的属性
                    /*
                    student.setStuId(resultSet.getInt("stuid"));
                    student.setStuName(resultSet.getString("stuname")
                    比如"stuid"应该通过setStuId
                     */
                    for (String columnName : columnNames) {//遍历列名
                        String methodName = "set" + columnName;//装饰,set某一属性
                        for (Method declaredMethod : declaredMethods) {//遍历所有方法
                            //忽略大小写,通过反射获得的方法名,如果相等,则该方法为对此属性进行赋值的方法
                            if(declaredMethod.getName().equalsIgnoreCase(methodName)){
                                //不确定类为什么类型,因此为object
                                //给某一对象赋值,值为某一列中取出的值
                                declaredMethod.invoke(stu,resultSet.getObject(columnName));
                                break;
                            }//end if
                        }//end for method
                    }//end for columnname





                    students.add(stu);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            }//end while
            return students;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            try {
                //5关闭资源
                if(resultSet != null){
                    resultSet.close();
                }
                if(pps != null){
                    pps.close();
                }
                if(connection != null){
                    connection.close();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }//end finally
        return null;
    }

编写操作实现类Test:

public class Test{
    public static void main(String[] args) {
   		/*
        List<Student> allStudent =dao.getAllStudent();
        for (Student student : allStudent) {
            System.out.println(student.getStuId()+","+student.getStuName()+","+student.getTeacherid());
        }
        */
        
		List<Student> allStudent =dao.getAllStudent(Student.class);
        for (Student student : allStudent) {
            System.out.println(student.getStuId()+","+student.getStuName()+","+student.getTeacherid());
        }//end for

    }//end main
}//end class

输出结果:

columnName = stuid
columnName = stuname
columnName = teacherid
1,张三,3
2,李四,1
3,王五,3
4,赵六,1
5,花花,1
6,潇潇,2

通过观察反射处理结果集的两个代码示例,可以发现重复步骤的代码大同小异,因此我们可以自定义一个工具类DBUtil,在类中将上述操作的重复代码以方法的形式进行封装,提高代码的简洁性

程序中重复代码的封装及运用可阅读文章:JDBC中自定义工具类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Selcouther

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值