一、JDBC简介
1.1 JDBC概念
- jdbc(java Database Connectivity)java连接数据库的规范(标准),可以使用java语言连接数据库完成CRUD操作
1.2 JDBC的核心思想
- java中定义了访问数据库的接口,可以为多种关系型数据库提供统一的访问方式。由数据库厂商提供驱动实现类(Driver数据库驱动)
- 图

二、JDBC连接工具类的封装
2.1 代码演示
package Utils;
import java.sql.*;
public class ConnectionUtilityClass {
private static ConnectionUtilityClass cuc;
private static Connection conn;
private ConnectionUtilityClass() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/qf?characterEncoding=utf-8&serverTimezone=UTC&useSSL=false";
String username = "数据库用户名";
String password = "数据库密码";
conn = DriverManager.getConnection(url, username, password);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
synchronized (ConnectionUtilityClass.class) {
if (cuc == null) {
cuc = new ConnectionUtilityClass();
}
return conn;
}
}
public static Boolean closeConnection(ResultSet rs, Statement st) {
synchronized (ConnectionUtilityClass.class) {
try {
if (rs != null) {
rs.close();
}
if (st != null) {
st.close();
}
if (conn != null) {
conn.close();
cuc = null;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
return false;
}
return true;
}
}
}
三、主键回显
3.1 问题的产生
- 例如:有A、B 两个表,B表保存A表的主键,并且A表的主键设置为自增,如何当A表插入数据时,同时返回A表主键插入B表
3.2 问题解决
- 代码实现
package Demo03;
import Utils.ConnectionUtilityClass;
import java.sql.*;
public class MethodSet {
public void insertData() {
Connection conn;
PreparedStatement ps = null;
ResultSet keys = null;
try {
conn = ConnectionUtilityClass.getConnection();
ps = conn.prepareStatement("insert into students(username,password) values (?,?)", Statement.RETURN_GENERATED_KEYS);
ps.setString(1, "曹操");
ps.setString(2, "123");
ps.executeUpdate();
keys = ps.getGeneratedKeys();
while (keys.next()) {
int anInt = keys.getInt(1);
ps = conn.prepareStatement("insert into book (name,stuid) values (?," + anInt + ")");
ps.setString(1, "bb");
ps.executeUpdate();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
ConnectionUtilityClass.closeConnection(keys, ps);
}
}
}
- 测试类
package Demo03;
public class Test {
public static void main(String[] args) {
MethodSet methodSet = new MethodSet();
methodSet.insertData();
}
}
四、一次性多条数据插入
- 实体类
package Demo02.model;
public class Student {
private String username;
private String password;
public Student() {
}
;
public Student(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "Student{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
- Dao类
package Demo02.Dao;
import Demo02.model.Student;
import Utils.ConnectionUtilityClass;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
public class MethodSet {
public void insertMultipleData(List<Student> list) {
Connection conn;
PreparedStatement ps = null;
conn = ConnectionUtilityClass.getConnection();
try {
ps = conn.prepareStatement("insert into students (username,password) values (?,?)");
for (int i = 0; i < list.size(); i++) {
ps.setString(1, list.get(i).getUsername());
ps.setString(2, list.get(i).getPassword());
ps.addBatch();
}
int[] ints = ps.executeBatch();
if (ints.length == list.size()) {
System.out.println("成功插入:" + ints.length + "条");
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
ConnectionUtilityClass.closeConnection(null, ps);
}
}
}
- 测试类
package Demo02;
import Demo02.Dao.MethodSet;
import Demo02.model.Student;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
MethodSet ms = new MethodSet();
List<Student> list = new ArrayList<>();
list.add(new Student("夏利", "123"));
list.add(new Student("夏利", "123"));
list.add(new Student("夏利", "123"));
list.add(new Student("夏利", "123"));
list.add(new Student("夏利", "123"));
ms.insertMultipleData(list);
}
}
五、数据库连接池
5.1 连接池的封装
package Demo04;
import com.alibaba.druid.pool.DruidDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class ConnectionPool{
private static DruidDataSource ds = null;
private ConnectionPool(){};
static {
ds = new DruidDataSource();
ds.setUrl("jdbc:mysql://localhost:3306/qf?characterEncoding=utf-8&serverTimezone=UTC&useSSL=false");
ds.setUsername("数据库用户名");
ds.setPassword("数据库密码");
ds.setInitialSize(100);
ds.setMinIdle(50);
ds.setMaxWait(1000*60);
ds.setMaxActive(200);
}
public static Connection getConnection() {
synchronized (ConnectionPool.class) {
if (ds != null) {
try {
return ds.getConnection();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
return null;
}
}
public static boolean closeConnection(ResultSet rs, Statement st,Connection conn){
synchronized (ConnectionPool.class) {
try {
if (rs != null) {
rs.close();
}
if (st != null) {
st.close();
}
if (conn != null) {
conn.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
return false;
}
}
return true;
}
}
5.2 测试类
package Demo04;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Test01 {
public static void main(String[] args) {
Connection conn = ConnectionPool.getConnection();
if (conn != null) {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement("insert into students (username,password) values (?,?)");
ps.setString(1,"小凡凡");
ps.setString(2,"asd");
int i = ps.executeUpdate();
if (i > 0) {
System.out.println("更新成功:" + i);
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
ConnectionPool.closeConnection(null, ps, conn);
}
}else {
System.out.println("获连接为空");
}
}
}
六、SQL注入问题
6.1 SQL注入问题的描述
- 用户输入的数据中有SQl关键字或语法并且参与了SQL语句的编译,导致结果为true,一直得到正确的结果
6.2 解决方法
- 解决:在输入数据前进行对SQL语句的预编译,然后再进行填充数据,填充进去的数据无论是啥都为数值,如sql关键字将被转义
- 使用PreparedStatement 继承了 Statement 接口,执行 SQL 语句的方法无异
- PreparedStatement作用
A.预编译SQL语句,效率高
B.避免SQL注入,安全
C.可以动态的的填充数据,执行多个同构SQL语句