java Jdbc 编程之编写Jdbc工具类,事务和批处理

目录

编写Jdbc工具类

由于每个Jdbc程序都需要连接数据库和关闭资源,因此可以将它们封装中一个工具类方便调用

代码

package com.thinknet.jdbc;

import java.io.FileReader;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;

public class JdbcUtils {
    private static String user;
    private static String password;
    private static String driver;
    private static String url;
    static {
        try {
            //读取配置文件建立连接
            Properties properties = new Properties();
            properties.load(new FileReader("src/mysql.properties"));
            user = properties.getProperty("user");
            password=properties.getProperty("password");
            driver=properties.getProperty("driver");
            url=properties.getProperty("url");
            Class.forName(driver);

        } catch (IOException | ClassNotFoundException e) {
            //最好将编译异常转成运行时异常,调用者可以选择捕获异常进行处理,也可默认处理
            throw  new  RuntimeException(e);
        }


    }
    public static Connection getConnection(){
        //返回连接
        try {
            return DriverManager.getConnection(url,user,password);
        } catch (SQLException e) {
            //转换成运行时异常
            throw new RuntimeException(e);
        }
    }
    public static void close(ResultSet resultSet, Statement statement ,Connection connection){
        //如果不为null就关闭连接
        try {
            if(resultSet!=null){
                resultSet.close();
            }
            if(statement!=null){
                statement.close();
            }
            if(connection!=null){
                connection.close();
            }
        } catch (SQLException e) {
            //转成运行时异常
            throw new RuntimeException(e);
        }
    }

}

应用:

用Jdbc工具类连接数据库,查询,更新数据库

package com.thinknet.jdbc;

import java.sql.*;

/**
 * 使用Jdbc工具类
 */
public class JdbcUtilsUse {
    public static void main(String[] args) {
        //更新数据库
       // update();
        //查询数据库
        select();
    }
    public static void update(){
        String sql="update actor set `name`=? where `id`=?";
        //获取连接
        Connection connection=null;
        PreparedStatement preparedStatement=null;
        try {
             connection = JdbcUtils.getConnection();//调用工具类获取连接
             preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,"king");
            preparedStatement.setInt(2,1);
            preparedStatement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(null,preparedStatement,connection);//调用工具类关闭资源
        }


    }
    public static void select(){
        String sql="select `id`,`name`,`sex`,`borndate`,`phone` from `actor`";
        
        Connection connection=null;
        PreparedStatement preparedStatement=null;
        ResultSet resultSet=null;
        try {
            connection=JdbcUtils.getConnection();//调用工具类获取连接
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()){
                int id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                String sex = resultSet.getString("sex");
                Date borndate = resultSet.getDate("borndate");
                String phone = resultSet.getString("phone");
                System.out.println("\t"+id+"\t"+name+"\t"+sex+"\t"+borndate+"\t"+phone+"\t");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(resultSet,preparedStatement,connection);//调用工具类关闭资源
        }
    }
}

事务处理

基本介绍:

  1. 在jdbc程序中当一个Connection对象创建时,默认情况下是自动提交事务:每次执行一条sql语句,如果执行成功,就会向mysql数据库自动提交 而不能回滚.
  2. Jdbc程序为了让多条sql语句作为一个整体执行,需要使用事务.
  3. 调用Connection对象的setAutoCommit(false)可以取消自动提交事务.
  4. 在所有SQL语句成功执行后调用Connection对象的commit()方法提交事务.
  5. 在某个sql语句执行失败或出现异常时,调用rollback()方法回滚事务

案例:

 public static void transferAccounts()  {
        String sql1 ="update `account` set balance = balance-1000 where id= ?";
        String sql2="update `account` set balance=balance+1000 where id=?";
        double money=1000;
        Connection connection=null;
        PreparedStatement preparedStatement=null;
        try {
            connection=JdbcUtils.getConnection();
            connection.setAutoCommit(false); //开启了事务
            preparedStatement=connection.prepareStatement(sql1);
            preparedStatement.setInt(1,1);
            preparedStatement.executeUpdate();
            preparedStatement=connection.prepareStatement(sql2);

            preparedStatement.setInt(1,2);
            preparedStatement.executeUpdate();
            connection.commit(); //当所有任务执行完后提交事务
        } catch (SQLException e) {
            try {
                connection.rollback(); //如果在执行sql语句的过程中出现了异常,回滚事务
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            JdbcUtils.close(null,preparedStatement,connection); //关闭资源
        }
    }

上面的代码模拟了转账操作,转账的过程应该视为一个整体,一个人的账户金额少了多少,令一个人就应该多多少,不能一个人的账户金额少了,另一个人的账户金额却不增加,这就要求出账的sql语句和进账的SQL语句应该同时成功,或同时失败,不能一个成功,一个失败.所以要用到事务,只有都成功了,才真正改变数据库,否则就回滚事务

批处理

基本介绍:

  1. 当需要成批插入或更新记录时,可使用java的批量更新机制,该机制允许多条语句一次提交给数据库批量处理,通常情况下,比单独提交更有效率
  2. Jdbc批处理包含下面方法:
    addBatch():添加需要批处理的SQL语句或参数
    executeBatch(): 执行批量处理语句
    clearBatch(): 情况批处理包的语句
  3. Jdbc连接mysql时,向要用批处理,要在url加上参数?rewriteBatchedStatements=true
  4. 批处理往往和PreparedStatement一起搭配使用,可以既减少编译次数,又减少运行次数,效率大大提高

案例:

不进行批处理:

 public static void noBatch()  {
        String sql="insert into admin2 values(?,?)";
        Connection connection=null;
        PreparedStatement preparedStatement=null;
        //获取连接
        try {
            connection = JdbcUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            long state=System.currentTimeMillis();
            for (int i=1;i<=5000;i++){
                preparedStatement.setString(1,"jack"+i);
                preparedStatement.setString(2,"666");
                preparedStatement.executeUpdate();
            }
            long end=System.currentTimeMillis();
            System.out.println("耗时: " + (end-state)+ " ms");//耗时: 3340 ms
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(null,preparedStatement,connection);
        }

    }

输出:

耗时: 3340 ms

批处理:

public static void Batch() {
        //注意:要在url上加参数?rewriteBatchedStatements=true
        String sql="insert into admin2 values(?,?)";
        Connection connection=null;
        PreparedStatement preparedStatement=null;
        //获取连接
        try {
            connection = JdbcUtils.getConnection();
            preparedStatement = connection.prepareStatement(sql);
            long state=System.currentTimeMillis();
            for (int i=1;i<=5000;i++){
                preparedStatement.setString(1,"jack"+i);
                preparedStatement.setString(2,"666");
                //添加需要批处理的SQL语句或参数
                //1. 第一次进入后创建ArrayList() ->elementData->Object[]
                //2. 接着将预处理后的SQL语句放入Object[]中
                //3. 如果满了,就按1.5倍扩容
                //4. 到达指定的数就executeBatch
                //5. 批处理会大大减少发送sql语句的网络开销,减少编译次数,效率提高
               /*源码:
                public void addBatch() throws SQLException {
                    synchronized(this.checkClosed().getConnectionMutex()) {
                        if (this.batchedArgs == null) {
                            this.batchedArgs = new ArrayList();
                        }

                        for(int i = 0; i < this.parameterValues.length; ++i) {
                            this.checkAllParametersSet(this.parameterValues[i], this.parameterStreams[i], i);
                        }

                        this.batchedArgs.add(new com.mysql.jdbc.PreparedStatement.BatchParams(this.parameterValues, this.parameterStreams, this.isStream, this.streamLengths, this.isNull));
                    }
                }
                */
                preparedStatement.addBatch();
                if(i%1000==0){ //没以前条处理一次
                    //执行批量处理语句
                    preparedStatement.executeBatch();
                    //清空批处理包的语句
                    preparedStatement.clearBatch();

                }
                else if (5000-i<1000){ //处理不足sql语句1000条的情况
                    //执行批量处理语句
                    preparedStatement.executeBatch();
                    //清空批处理包的语句
                    preparedStatement.clearBatch();
                }
            }
            long end=System.currentTimeMillis();
            System.out.println("耗时: " + (end-state)+ " ms");//耗时: 924 ms
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(null,preparedStatement,connection);
        }

    }

输出:

耗时: 924 ms

上面的代码是向表中插入5000条数据,不进行批处理和批处理的情况下的时间消耗,可以开到批处理比不进行批处理要快一些.

全部评论

相关推荐

xdm&nbsp;早上喝奶茶差点喷出来。事情是这样的,我们班有个哥们儿,简称&nbsp;L,去年秋招拿了字节sp,专业方向是后端。我们当时都震惊:这哥们儿平时课上从来不发言,期末小组作业基本是划水的那种,刷题平台&nbsp;commit记录我点进去看过,绿格子稀稀拉拉。但他面试一路绿灯。一面二面三面&nbsp;hr&nbsp;面,全过,给的还是sp。当时班级群里恭喜他的、问他经验的、约饭的,热闹了一周。他说自己"运气好,准备充分"。我们都信了,直到三月初他入职。入职第二周开始,班里另一个进字节的同学W(在隔壁组的)开始跟我他的不对劲。一开始是写代码慢,后来写不出来,再后来是组里&nbsp;mentor&nbsp;让他fix&nbsp;一个简单&nbsp;bug&nbsp;都搞了一下午没动静。最离谱的是上周。W&nbsp;说他们大部门搞了个新人分享会,让新人讲一下自己负责模块的设计思路。L&nbsp;上去讲了&nbsp;20分钟,全程念稿子,问答环节别人随便问一个"那你这里为什么用&nbsp;Redis&nbsp;不用&nbsp;Memcached",他直接卡&nbsp;30秒说"这个我回去再确认一下"。会后他&nbsp;mentor&nbsp;直接找&nbsp;leader&nbsp;谈,leader&nbsp;找&nbsp;hr&nbsp;谈,hr调出了他面试录像,全程对比口型和回答节奏,发现他二三面有大量时长在偷偷看屏幕外(推测开了双机位&nbsp;AI&nbsp;答题)。(这段是&nbsp;W后来转述给我的,他自己也是听他组里同事八卦来的)昨天下班前,W&nbsp;告诉我L&nbsp;被辞退了,让他自己走,不走就走仲裁但会发函到学校。L&nbsp;现在已经回学校了,朋友圈仅三天可见。我说真的,我不是个心眼小的人,但是我看到这个消息的时候真的有种"嗯,挺好"的感觉。去年秋招我投字节后端,简历挂。我准备了八个月,背&nbsp;八股&nbsp;+&nbsp;刷&nbsp;500&nbsp;题&nbsp;+项目改了三版,连面试机会都没拿到。班里这哥们儿凭着一个外挂上岸,最后还是被甩出来了。不是说作弊就一定会被发现,但是当面试拿到的&nbsp;offer远远超出真实能力的时候,迟早会有这一天。试用期三个月不是给你过家家的,是真的要写代码、要在会议上回答问题、要扛需求的。我现在反而有点同情他。同情他相信"上岸就是终点"。发出来不是为了嘲笑谁,就是想说给那些正在被身边作弊上岸的同学搞得很&nbsp;emo&nbsp;的&nbsp;uu&nbsp;们听——别急,回旋镖很长,但它一定会回来。你继续刷你的题,写你的项目,背你的八股。该是你的迟早是你的,不是你的早晚还得还回去。xdm&nbsp;共勉。
牛客12588360...:我不想评论面试方式,作弊是绝对不对的,但是你八股加刷题也不过是个做题小子,他穿帮纯粹是他菜,你也没有高明到哪里去
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务