JDBC

图1

  1. 创建工程,导入驱动jar包:

    mysql-connector-java-5.1.48.jar

  2. 注册驱动

    Class.forName("com.mysql.jdbc.Driver");

  3. 获取连接
    Connection conn = DriverManager.getConnection(url, username, password);

  4. 定义SQL语句
    String sql ="update...";

  5. 获取执行SQL对象
    Statement stmt = conn.createStatement();

  6. 执行SQL
    stmt.executeUpdate(sql);

  7. 处理返回结果

  8. 释放资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.jpc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class JDBCDemo {
public static void main(String[] args) throws Exception {
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");

// 获取链接
String url = "jdbc:mysql://127.0.0.1:3306/web2";
String username = "root";
String password = "123123";
Connection conn = DriverManager.getConnection(url, username, password);

// 定义sql
String sql = "insert into user value(2, 'ly', 18)";

// 获取执行sql的对象的Statement
Statement stmt = conn.createStatement();

// 执行sql
int count = stmt.executeUpdate(sql);

// 处理结果
System.out.println(count);

// 释放资源
stmt.close();
conn.close();

}
}

JDBC-API

DriverManager

1
2
3
DriverManager.registerDriver(); //注册驱动(可以不写)
DriverManager.getConnection(url, user, password); //url 链接路径,user用户名, password用户密码
// url : (jdbc:mysql://ip地址:端口/数据库名称)

Connection

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
conn.createStatement();//获取执行sql的对象

//事务管理
conn.setAutoCommit(boolean autoCommit); //ture为自动提交事务, false为手动,开启事务
commit(); //提交事务
rollback(); //回滚事务

try{
//开启事务
conn.setAutoCommit(false);
//执行sql
int count = stmt.executeUpdate(sql);
// 处理结果
System.out.println(count);

//提交事务
conn.commit();
}catch(Exception throwables){
//回滚事务
conn.rollback();
throwables.printStackTrace();
}

Statement

执行sql语句

1
2
3
4
5
6
7
8
9
executeUpdate(sql); //执行DML、DDL语句,返回值:DML返回受影响的行数,DDL返回可能是0(只要不报错就是执行正确)
executeQuery(sql); // 执行DQL语句, 返回值:ResultSet(结果集对象)

// DML、DDL
String sql1 = "create database db2";
Statement stmt = conn.createStatement();
int cnt1 = stmt.executeUpdate(sql1); // 执行DDL
String sql2 = "insert into user value(2, 'ly', 18)";
int cnt2 = stmt.executeUpdate(sql2); // 执行DML

ResultSet

1
2
3
4
5
6
7
ResultSet stmt.executeQuery(sql); //执行DQL语句

//获取查询结果
boolean next(): //将光标移动到下一行,检查是否为有效行 true(有效)
xxx getXxx(参数):
//xxx是数据类型如String getString();
//参数int:列的编号,String 列的名称

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package com.jpc;

import com.pojo.Account;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class JDBCDemo1_ResultSet {
public static void main(String[] args) throws Exception {
// 注册驱动
// Class.forName("com.mysql.jdbc.Driver");

// 获取链接
String url = "jdbc:mysql://127.0.0.1:3306/web2?useSSL=false";
String username = "root";
String password = "123123";
Connection conn = DriverManager.getConnection(url, username, password);

// 定义sql
String sql = "select * from user";

// 获取执行sql的对象的Statement
Statement stmt = conn.createStatement();

// 执行sql
ResultSet rs = stmt.executeQuery(sql);

//创建一个集合
List<Account> list = new ArrayList<>();

// 处理结果
while(rs.next()){

//创建对象
Account account = new Account();
//获取数据
int id = rs.getInt(1);
String name = rs.getString(2);
int age = rs.getInt(3);
account.setId(id);
account.setName(name);
account.setAge(age);
list.add(account);
}

System.out.println(list);

//释放资源
rs.close();
stmt.close();
conn.close();
}
}

SQL注入与PreparedStatement

SQL注入

SQL注入原理,通过SQL语句去完成登录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package com.jpc;

import com.pojo.Account;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class JDBCUserLogin {
public static void main(String[] args) throws Exception {
// 注册驱动
// Class.forName("com.mysql.jdbc.Driver");

// 获取链接
String url = "jdbc:mysql://127.0.0.1:3306/web2?useSSL=false";
String username = "root";
String password = "123123";
Connection conn = DriverManager.getConnection(url, username, password);


String name = "jpdasdadsadsac";
String pwd = "' or '1'='1";

// 定义sql
String sql = "select * from user where username = '"+name+"' and password = '"+pwd+"'";

System.out.println(sql);
// 获取执行sql的对象的Statement
Statement stmt = conn.createStatement();

// 执行sql
ResultSet rs = stmt.executeQuery(sql);


if(rs.next()){
System.out.println("登录成功~");
}else{
System.out.println("登录失败~");
}

//释放资源
rs.close();
stmt.close();
conn.close();
}
}

上述代码运行结果:

1
2
select * from user where username = 'jpdasdadsadsac' and password = '' or '1'='1'
登录成功~

因为登录密码相当于SQL注入,截断了password并且加了一个or ‘1’ = ‘1’ 导致随便输入用户名也会成功登录。

PrearedStatement预防SQL注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
String name = "jpdasdadsadsac";
String pwd = "' or '1'='1";

// 定义sql,参数用?替代
String sql = "select * from user where username = ? and password = ?";

// 获取执行sql的对象的Statement
PreparedStatement pstmt = conn.prepareStatement(sql);

//设置两个参数(设置?的值)
pstmt.setString(1, name);
pstmt.setString(2, pwd);
// 执行sql
ResultSet rs = pstmt.executeQuery();


if(rs.next()){
System.out.println("登录成功~");
}else{
System.out.println("登录失败~");
}

输出结果:登录失败

原理:将敏感字符串进行转义

  1. 在获取PreparedStatement对象时,将sql语句发送给mysql服务器
    进行检查,编译(这些步骤很耗时)
  2. 执行时就不用再进行这些步骤了,速度更快
  3. 如果sql模板一样,则只需要进行一次检查、编译

PreparedStatement好处:

  1. 预编译SQL,性能更高
  2. 防止SQL注入

开启预编译功能:useServerPrepStmts=true;

数据库连接池

数据库连接池简介

  • 数据库连接池是个容器,负责分配、管理数据库连接(Connection)
  • 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;
  • 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏
  • 好处:
    • 资源重用
    • 提升系统响应速度。
    • 避免数据库连接遗漏。

数据库连接池实现

  • 标准接口:DataSource
  • 官方(SUN)提供的数据库连接池标准接口,由第三方组织实现此接口。
  • 功能:获取连接:Connection getConnection()
  • 常见的数据库连接池:
    • DBCP
    • C3P0
    • Druid(德鲁伊)
  • Druid连接池是阿里巴巴开源的数据库连接池项目
  • 功能强大,性能优秀,是Java语言最好的数据库连接池之一。