JDBC
创建工程,导入驱动jar包:
mysql-connector-java-5.1.48.jar
注册驱动
Class.forName("com.mysql.jdbc.Driver");
获取连接
Connection conn = DriverManager.getConnection(url, username, password);
定义SQL语句
String sql ="update...";
获取执行SQL对象
Statement stmt = conn.createStatement();
执行SQL
stmt.executeUpdate(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
| 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);
String sql = "insert into user value(2, 'ly', 18)";
Statement stmt = conn.createStatement();
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);
|
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();
conn.setAutoCommit(boolean autoCommit); commit(); rollback();
try{ conn.setAutoCommit(false); 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); executeQuery(sql);
String sql1 = "create database db2"; Statement stmt = conn.createStatement(); int cnt1 = stmt.executeUpdate(sql1); String sql2 = "insert into user value(2, 'ly', 18)"; int cnt2 = stmt.executeUpdate(sql2);
|
ResultSet
1 2 3 4 5 6 7
| ResultSet stmt.executeQuery(sql);
boolean next(): xxx getXxx(参数):
|
例子
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 {
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 sql = "select * from user";
Statement stmt = conn.createStatement();
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 {
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";
String sql = "select * from user where username = '"+name+"' and password = '"+pwd+"'";
System.out.println(sql); Statement stmt = conn.createStatement();
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";
String sql = "select * from user where username = ? and password = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name); pstmt.setString(2, pwd); ResultSet rs = pstmt.executeQuery();
if(rs.next()){ System.out.println("登录成功~"); }else{ System.out.println("登录失败~"); }
|
输出结果:登录失败
原理:将敏感字符串进行转义
- 在获取PreparedStatement对象时,将sql语句发送给mysql服务器
进行检查,编译(这些步骤很耗时)
- 执行时就不用再进行这些步骤了,速度更快
- 如果sql模板一样,则只需要进行一次检查、编译
PreparedStatement好处:
- 预编译SQL,性能更高
- 防止SQL注入
开启预编译功能:useServerPrepStmts=true;
数据库连接池
数据库连接池简介
- 数据库连接池是个容器,负责分配、管理数据库连接(Connection)
- 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;
- 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏
- 好处:
- 资源重用
- 提升系统响应速度。
- 避免数据库连接遗漏。
数据库连接池实现
- 标准接口:DataSource
- 官方(SUN)提供的数据库连接池标准接口,由第三方组织实现此接口。
- 功能:获取连接:Connection getConnection()
- 常见的数据库连接池:
- Druid连接池是阿里巴巴开源的数据库连接池项目
- 功能强大,性能优秀,是Java语言最好的数据库连接池之一。