暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

jdbc批处理、自动主键和大数据处理

Java笔记录 2019-03-01
742
批处理、自动主键和大数据处理


批处理


当需要向数据库中执行多条语句的时候,如果一条一条的发送显然会使效率很低,这时就要使用批处理了,使用

addBatch()方法将要执行的sql语句添加到批处理中,然后使用executeBatch()方法执行批处理,最后调用

clearBatch()方法清除,以防止数据太多时内存溢出。


实现批处理的时候当然也有两种方式,一种是使用

Statement类,另一种方法时使用PreparedStatement,使用Statement类要首先编译好sql语句,如果批处理的

sql语句规律性很强,则还是使用PreparedStatement比较好。


package com.demo.test;

import java.sql.*;

public class BatchTest1 {
    private static final String USER = "root";
    private static final String PASS = "ForMe=520";
    private static final String URL = "jdbc:mysql://localhost:3306/test01";
    private static final String DRIVER = "com.mysql.jdbc.Driver";


    public static void main(String[] args) throws ClassNotFoundException {

//            batchTest();
            batchTest1();
    }

    public static Connection getConn() throws SQLException {
        Connection connection = DriverManager.getConnection(URL,USER,PASS);
        return connection;
    }

    public static void batchTest() throws ClassNotFoundException, SQLException {
        Class.forName(DRIVER);
        Connection connection = getConn();
        String sql = "INSERT INTO THINGS(id,name) VALUES (?,?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        for(int i = 0; i < 50; i++){
            preparedStatement.setInt(1,i);
            preparedStatement.setString(2,"username" + i);

            preparedStatement.addBatch();
            if(i%2 == 0) {
                preparedStatement.executeBatch();//执行批处理
                preparedStatement.clearBatch();  //清除处理,防止数量过多时内存溢出
            }
        }
        preparedStatement.executeBatch();
        preparedStatement.clearBatch();
        preparedStatement.close();
        connection.close();
    }

    public static void batchTest1(){
        try {
            Class.forName(DRIVER);
            Connection connection = getConn();
            String sql1 = "UPDATE THINGS SET name='UPDATED1' WHERE id=10 ";
            String sql2 = "UPDATE THINGS SET name='UPDATED2' WHERE id=20";
            String sql3 = "UPDATE THINGS SET name='UPDATED3' WHERE id=30";
            String sql4 = "UPDATE THINGS SET name='UPDATED4' WHERE id=40";

            Statement statement = connection.createStatement();
            statement.addBatch(sql1);
            statement.addBatch(sql2);
            statement.addBatch(sql3);
            statement.addBatch(sql4);

            statement.executeBatch();
            statement.clearBatch();
            statement.close();
            connection.close();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
}


由上述例子可以看出,如果使用 Statement插入50条规律性很强的语句会有多么的麻烦。


小总结:
使用PreparedStatement的优点:发送的是预编译后的SQL语句,执行效率高。
使用PreparedStatement的缺点:只能应用在SQL语句相同,但参数不同的批处理中。因此此种形式的批处理经常用于在同一个表中批量插入数据,或批量更新表的数据。


自动主键


首先先来了解一下主键是什么?

在数据表中每一行都应该有可以为以标识自己的一列(或一组列),例如订单有订单编号,学生有学生的学号等。如果没有主键,更新或者删除特定的行就会很困难,因为没有安全的保证只涉及相关的行。


定义主键的条件:

1、任意的两行都不具备相同的主键值

2、主键值不允许为空


何为自动主键?

也即是有自动增加约束(AUTO_INCREMENT)的主键,这样对行进行插入时会自动的增加主键,而无需在手动操作主键。


public static void auoPK(){
        try {
            Class.forName(DRIVER);
            Connection connection = getConn();
            ResultSet resultSet = null;
            String sql = "INSERT INTO THINGS (name) VALUES (?)";
            PreparedStatement preparedStatement = connection.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);
            preparedStatement.setString(1,"username");
            int num = preparedStatement.executeUpdate();

            if(num > 0) {
                 resultSet = preparedStatement.getGeneratedKeys();  //获取到自动主键的值
                if (resultSet.next()) {
                    System.out.println(resultSet.getInt(1));
                }
            }
            preparedStatement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }


处理大数据


大数据分为文本类型的和二进制类型的,文本类型的大数据mysql用Text代替,二进制类型的使用blob,其中的类型又可分为:

TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT

TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB


先来看文本类型存进数据库和从数据库中读取


存入数据库


public static void addBigText(){
        try {
            Connection connection = getConn();
            Class.forName(DRIVER);
            String sql = "INSERT INTO bigtest (bigdata) VALUES (?)";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            String path = BatchTest1.class.getClassLoader().getResource("data.txt").getPath();//获取文件路径
            File file = new File(path);
            FileReader fileReader = new FileReader(file);

            preparedStatement.setCharacterStream(1,fileReader,file.length()); //MySQL中存入Text类型

            int num = preparedStatement.executeUpdate();

            if(num > 0)
                System.out.println("插入大文本成功");
            preparedStatement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }


结果



可以看到确实是存进了数据库


下面就把它读出来


public static void readBigText(){
        try {
            Connection connection = getConn();
            String sql = "SELECT * FROM bigtest";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            ResultSet resultSet = preparedStatement.executeQuery();
            if(resultSet.next()){
                Reader reader = resultSet.getCharacterStream("bigdata");  //读取到数据库中的内容
                FileWriter fileWriter = new FileWriter("F://big.txt");//下面的内容就相当于对文件的操作
                char[] chars = new char[1024];
                int len = 0;
                while((len = reader.read(chars)) != -1){
                    fileWriter.write(chars,0,len);
                    fileWriter.flush();
                }
                fileWriter.close();
                reader.close();
            }
            preparedStatement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


把它存在F盘下的big.txt中,打开F盘发现确实读了出来,并且与原文本一致。


二进制类型的存取


二进制类型的存取和文本类型存取的原理是一样的,只不过是把字符流改成字节流,把读取文件改成setBinaryStream和getBinaryStream,其余的操作完全一致


存进数据库


public static void addBigBlob(){
        try {
            Connection connection = getConn();
            Class.forName(DRIVER);
            String sql = "INSERT INTO bigblob (bigblob) VALUES (?)";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            String path = BatchTest1.class.getClassLoader().getResource("jdbc.jpg").getPath();//获取文件路径
            File file = new File(path);
            FileInputStream fileInputStream = new FileInputStream(file);

            preparedStatement.setBinaryStream(1,fileInputStream,file.length()); //MySQL中存入Text类型

            int num = preparedStatement.executeUpdate();

            if(num > 0)
                System.out.println("插入二进制类型成功");
            preparedStatement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }


从数据库中读取


public static void readBigBlob(){
        try {
            Connection connection = getConn();
            String sql = "SELECT * FROM bigblob";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            ResultSet resultSet = preparedStatement.executeQuery();
            if(resultSet.next()){
                InputStream inputStream = resultSet.getBinaryStream("bigblob");  //读取到数据库中的内容
                FileOutputStream fileWriter = new FileOutputStream("F://bigbolb.jpg");//下面的内容就相当于对文件的操作
                byte[] bytes = new byte[1024];
                int len = 0;
                while((len = inputStream.read(bytes)) != -1){
                    fileWriter.write(bytes,0,len);
                    fileWriter.flush();
                }
                fileWriter.close();
                inputStream.close();
            }
            preparedStatement.close();
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


结果




总结:本篇博客学习了jdbc中的批处理、自动主键和处理大数据三个知识点,要熟练掌握这三个知识点,以便在后续的开发中得心应手。




文章转载自Java笔记录,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论