目录
SQL注入
预编译操作对象
自定义JDBC工具类
1.创建配置文件
2.配置
3.在工具类中使用配置文件
批处理
注意事项
SQL注入
SQL注入是黑客对数据库进行攻击的常用手段之一,他们拼接一些恶意的sql语句,来获取他们想要的数据。
例:
select * from user where username='1' or '1'='1' and password='1' or '1' = '1';
利用sql语言的特点,即where后面的条件为真,来恶意查询数据,即可查询到全部数据
为了解决这个问题,我们要用到预编译操作对象,防止sql注入
预编译操作对象
PreparedStatement 用来防止SQL注入
//SQL语句中的值 全部用 ? 问号占位
String sql = "select * from user where username=? and password=?";
//获取一个预编译操作对象 PreparedStatement
PreparedStatement preparedStatement = conn.prepareStatement(sql);
//给问号赋值
preparedStatement.setString(1, uname);
preparedStatement.setString(2, pwd);ResultSet resultSet = preparedStatement.executeQuery(); //不用传sql
其他代码都与之前一致
执行程序后,没有查询到任何数据。
就是因为我们使用了预编译操作对象——preparedStatement
他的setString()方法中对非法单引号做了转义,使得坏人不能够得逞。
我们可以打印看一下
自定义JDBC工具类
首先建一个工具包,在里面定义JBDC工具类
但是,数据库、用户名和密码总不是固定不变的,当我们需要去改变时,需要打开这个工具类来改变数据,不如我们创建一个配置文件,使用配置文件来读取数据、修改数据来的方便。
1.创建配置文件
2.配置
3.在工具类中使用配置文件
批处理
即多条sql语句一起执行,当插入大量数据时,建议使用批处理。
statement.addBatch();//添加批处理,先将数据缓存起来
statement.executeBatch();//执行批处理
statement.clearBatch();//清空缓存
如果我们向数据库中一条条插入数据,如下:
package org.xingyun.demo;
import org.xingyun.bean.Bank;
import org.xingyun.utils.JDBCUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
public class demo5 {
public static void main(String[] args) throws SQLException {
ArrayList<Bank> list = new ArrayList<>();
for (int i = 0; i < 50000; i++) {
Bank bank = new Bank(1010+i,"zhangsan"+i,1000+i);
list.add(bank);
}
Connection conn = JDBCUtil.getConnection();
String sql="insert into bank(id, username, money) values (?,?,?)";
PreparedStatement preparedStatement = conn.prepareStatement(sql);
long l = System.currentTimeMillis();
for (Bank bank : list) {
preparedStatement.setInt(1,bank.getId());
preparedStatement.setString(2, bank.getUsername());
preparedStatement.setInt(3, bank.getMoney());
preparedStatement.executeUpdate();
}
long ll = System.currentTimeMillis();
System.out.println(ll-l);
JDBCUtil.close(conn,preparedStatement);
}
}
所用时间为:30322ms
sql语句是一条一条执行,则效率会非常低。
当需要插入大量数据时,我们使用批处理,就是sql语句多条执行,则效率会非常高。如下:
package org.xingyun.demo;
import org.xingyun.bean.Bank;
import org.xingyun.utils.JDBCUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
public class demo6 {
public static void main(String[] args) throws SQLException {
ArrayList<Bank> list = new ArrayList<>();
for (int i = 0; i < 5000; i++) {
Bank bank = new Bank(1010 + i, "zhangsan" + i, 1000 + i);
list.add(bank);
}
Connection conn = JDBCUtil.getConnection();
String sql = "insert into bank(id, username, money) values (?,?,?)";
PreparedStatement preparedStatement = conn.prepareStatement(sql);
long l = System.currentTimeMillis();
for (Bank bank : list) {
preparedStatement.setInt(1, bank.getId());
preparedStatement.setString(2, bank.getUsername());
preparedStatement.setInt(3, bank.getMoney());
preparedStatement.addBatch();
}
preparedStatement.executeBatch();
preparedStatement.clearBatch();
long ll = System.currentTimeMillis();
System.out.println(ll-l);
JDBCUtil.close(conn, preparedStatement);
}
}
所用时间为:6196
由此可见,时间缩短为不使用批处理时的五分之一。
可见,效率很高。
注意事项
但 提交的sql不能超过max_allowed_packet的设置值 不然报错
jdbc:mysql://localhost:3306/shopxxb2b2c?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&rewriteBatchedStatements=true
max_allowed_packet查询方法
进入mysql容器 运行show VARIABLES like 'max_allowed_packet';
1
mysql> show VARIABLES like 'max_allowed_packet';
+--------------------+------------+
| Variable_name | Value |
+--------------------+------------+
| max_allowed_packet | 1073741824 |
+--------------------+------------+
1 row in set
max_allowed_packet的单位为字节:-- 转化为Mb,就是1024Mb
mysql> select 1073741824/1024/1024;
+----------------------+
| 1073741824/1024/1024 |
+----------------------+
| 1024.00000000 |
+----------------------+
1 row in set
————————————————