JDBC中的SQL注入的问题、JDBC执行DML(insert、update、delete)操作和其他操作、JDBC读取数据并插入到表中(使用批量插入、多线程、线程池、连接池提高插入效率)、连接池

JDBC中的SQL注入问题

package com.shujia;
import java.sql.*;
public class MySQLJDBCDemo {
    public static void main(String[] args) throws Exception {
        // 1、加载驱动
        Class.forName("com.mysql.jdbc.Driver");

        // 2、创建连接
        // "jdbc:mysql://master(主机名):3306(mysql默认的端口号)/db1(库名)?useSSL=false","root(用户名)","123456(密码)"
        // ?(通过?来加参数)useSSL(在MySQL5.7版本之后默认含有SSL加密的连接)=false
        Connection conn = DriverManager.getConnection("jdbc:mysql://master:3306/db1?useSSL=false","root","123456");

        //// 3、创建Statement
        //Statement st = conn.createStatement();

        //实际上我们查询肯定不会是这样简单的查询,肯定会有查询的条件
        //ResultSet rs = st.executeQuery("select * from student");
        //加上条件
        //ResultSet rs = st.executeQuery("select * from student where clazz='文科一班'");
        //那么我又想查别的呢?where子句后面的条件又要去改变,所以我们用变量去代替
        //String clz = "'文科二班'";//一般这里变量的值我们不会去给他写死,将来需要进行传参
        
        //假如说将来传进来  文科二班 or 1=1  这样的值
        //观察运行结果发现,表中数据全部输出,并没有被筛选
        //String clz = "'文科二班' or 1=1"; //--直接使用变量拼接SQL会造成SQL注入问题
        // 4、通过Statement执行SQL
        //ResultSet rs = st.executeQuery("select * from student where clazz="+clz);
        
        //这里不加'' 是因为通过ps.setString(1, clz)传进去时自动添加了
        //此时 文科二班 or 1=1 相当于一整个字符串
        String clz = "文科二班 or 1=1";
        int ag = 23;
        
        //3、为了避免这样的问题使用prepareStatement
        // ? 相当于占位符,等会往里面设置值的时候会将其代替
        PreparedStatement ps = conn.prepareStatement("select * from student where clazz=? and age >?");
        
        // 4、通过PreparedStatement执行SQL
        // 先设置参数 从1开始编号
        ps.setString(1, clz);
        ps.setInt(2, ag);
        // 执行DQL时使用executeQuery方法
        // 再执行SQL
        ResultSet rs = ps.executeQuery();
        
        // 5、遍历ResultSet 获取返回的记录
        while (rs.next()) {
            int id = rs.getInt("id");
            String name = rs.getString("name");
            int age = rs.getInt("age");
            String gender = rs.getString("gender");
            String clazz = rs.getString("clazz");

            System.out.println(id + "," + name + "," + age + "," + gender + "," + clazz);
        }
        // 6、关闭连接
        ps.close();
        conn.close();
    }
}

JDBC执行DML(insert、update、delete)操作和其他操作

package com.shujia;
import java.sql.*;
public class MySQLJDBCDemo {
    public static void main(String[] args) throws Exception {
        // 1、加载驱动
        Class.forName("com.mysql.jdbc.Driver");

        // 2、创建连接
        // "jdbc:mysql://master(主机名):3306(mysql默认的端口号)/db1(库名)?useSSL=false","root(用户名)","123456(密码)"
        // ?(通过?来加参数)useSSL(在MySQL5.7版本之后默认含有SSL加密的连接)=false
        Connection conn = DriverManager.getConnection("jdbc:mysql://master:3306/db1?useSSL=false","root","123456");
        
        //通过PreparedStatement执行SQL
        PreparedStatement ps = conn.prepareStatement("select * from student where clazz=? and age >?");
        
        // 执行DML(insert、update、delete)操作 可以使用executeUpdate方法
        int i = ps.executeUpdate("update score set score=100");
        System.out.println(i); // 返回受影响的记录的条数

        // 其他操作使用execute方法
        boolean bool = ps.execute("create database if not exists db3");
        System.out.println(bool); // 指示执行的SQL有无返回值
        boolean bool2 = ps.execute("select * from score where score<0 limit 1");
        System.out.println(bool2);

        // 6、关闭连接
        ps.close();
        conn.close();
    }
}

JDBC读取数据并插入到表中

需求:通过JDBC读取数据并插入到表中

#使用批量插入、多线程、线程池、连接池提高插入效率

package com.shujia;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
//定义线程
public class InsertTask implements Runnable {
    //定义成员变量
    Connection conn;
    ArrayList<String[]> linesArr;
    int i;

    //通过有参的构造方法实现赋值
    public InsertTask(Connection conn, ArrayList<String[]> linesArr, int i) {
        this.conn = conn;
        this.linesArr = linesArr;
        this.i = i;
    }

    @Override
    public void run() {
        System.out.println("正在执行第" + i + "个任务");

        try {

            // 3、创建prepareStatement
            PreparedStatement ps = conn.prepareStatement("insert into student_like values(?,?,?,?,?)");

            for (String[] splits : linesArr) {
                // splits就是每一行数据都切好
                // 例如:1500100988,余鸿云,22,男,文科六班
                String id = splits[0];
                String name = splits[1];
                String age = splits[2];
                String gender = splits[3];
                String clazz = splits[4];

                // 设置参数
                ps.setInt(1, Integer.parseInt(id));
                ps.setString(2, name);
                ps.setInt(3, Integer.parseInt(age));
                ps.setString(4, gender);
                ps.setString(5, clazz);

                // 使用批量插入
                ps.addBatch(); // 将语句先放入Batch中
            }

            ps.executeBatch(); // 在循环外 进行批量处理
            ps.close();
            conn.close(); // 关闭连接池传入的连接并不会真正关闭,而是放回连接池
            System.out.println("第" + i + "个任务执行完成");
        } catch (Exception e) {
            System.out.println("发生了异常" + e);
        }
    }
}


    /**
     * 在MySQL中手动建表:
     * CREATE TABLE `student_like` (
     * `id` int(10) NOT NULL COMMENT '学生id',
     * `name` varchar(10) DEFAULT NULL COMMENT '学生姓名',
     * `age` int(2) DEFAULT NULL COMMENT '学生年龄',
     * `gender` varchar(1) DEFAULT NULL COMMENT '学生性别',
     * `clazz` varchar(5) DEFAULT NULL COMMENT '学生班级'
     * ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='学生信息表';
     */


package com.shujia;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import java.io.BufferedReader;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ReadAndWriteToMySQL {

    public static void main(String[] args) throws Exception {
        // 读取student.txt文件
        BufferedReader br = new BufferedReader(new FileReader("Java/data/students.txt"));
        String line;
        ArrayList<String[]> linesArr = new ArrayList<>();
        while ((line = br.readLine()) != null) {
            // 避免重复读取数据,在第一次读的时候将每一行数据切分后放入ArrayList
            linesArr.add(line.split(","));
        }
        br.close();

        // 使用线程池
        ExecutorService es = Executors.newFixedThreadPool(8);

        // 使用连接池
        // 配置
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:mysql://master:3306/db1");
        config.setUsername("root");
        config.setPassword("123456");
        config.addDataSourceProperty("connectionTimeout", "10000"); // 连接超时:1秒
        config.addDataSourceProperty("idleTimeout", "60000"); // 空闲超时:60秒
        config.addDataSourceProperty("maximumPoolSize", "10"); // 最大连接数:10
        config.addDataSourceProperty("useSSL", "false"); // 关闭使用SSL连接

        // 创建连接池
        HikariDataSource ds = new HikariDataSource(config);

        // show global status like "%Thread%"; 查看MySQL的连接数

        for (int i = 0; i < 100; i++) {
            // 每次从连接池中获取一个连接
            Connection conn = ds.getConnection();

            System.out.println("第" + i + "次插入");
            InsertTask task = new InsertTask(conn, linesArr, i);
            es.submit(task);
        }

        // 销毁线程池
        es.shutdown();
        // 销毁连接池
        ds.close();
    }
}

##Java字符串中的split()方法

根据传入的分割符,将字符串分割,返回一个String类型的数组

例如:

str = "ab,cd,ef "

String[] s = str.split(",");

##查看MySQL的连接数

show global status like "%Thread%"; 

##批量插入和批量处理

#批量插入
addBatch()//将语句先放入Batch中
#批量处理
executeBatch(); 

连接池

MySQL笔记总结

posted @ 2022-01-15 23:30  赤兔胭脂小吕布  阅读(127)  评论(0编辑  收藏  举报