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();