全称是JAVA DATE BASE Connectity(java数据库连接),可以为多种数据库提供统一的访问。即定义一个规范的接口,让各数据库厂商提供接口的具体实现类,这种实现类同时也被称作驱动。
(4个核心对象)
- DriverManager:用于注册驱动。
- Connection:与数据库创建连接。
- Statement:操作数据库sql语句的对象。
- ResultSet:结果集(存放由select语句查询到的数据信息)
(即根据4个核心类对象推导出的步骤并封装)
方式一:
直接注册驱动
DriverManager.registerDriver(new Driver());
方式二:(推荐使用)
通过反射的方式,实现驱动的加载
Class.forName("com.mysql.cj.jdbc.Driver");
注意:
Driver源代码
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
通过注册的JDBC驱动来建立数据库连接对象从而获取数据库的URL,用户名,密码来连接数据库
String url = "jdbc:mysql://localhost:3306/day04?serverTimezone=UTC&characterEnconding=utf-8";
Connection con = DriverManager.getConnection(url,"root","123456");
解析
String url = "jdbc:mysql://localhost:3306/day04?serverTimezone=UTC&characterEnconding=utf-8";
jdbc:是JDBC连接协议
mysq:// 是mysql数据库连接协议,即JDBC子协议
Localhost:3306 是主机和端口
day04 是指需要连接的数据库
serverTimezone=UTC:国际通用时区
characterEncoding=utf-8:数据库编码格式 (主要是解决数据库乱码的问题)
方式一:(该方式有弊端,会导致sql注入问题)
通过数据库连接对象获取操作数据库sql语句的对象Statement
String sql = "select * from user where username = '"+name+"' and password = '"+passwd+"';";
Statement stmt = con.createStatement();
模拟用户登录
需求:通过键盘录入来获取用户名和密码,同时在数据库中判断该用户是否存在
存在即登录成功,反之则失败。
代码一:
import java.sql.*;
import java.util.Scanner;
public class JDBCTest3 {
public static void main(String[] args) {
System.out.println("请输入用户名");
String name = new Scanner(System.in).nextLine();
System.out.println("请输入密码");
String passwd = new Scanner(System.in).nextLine();
//加载驱动
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
//建立连接
String url = "jdbc:mysql://localhost:3306/day04?serverTimezone=UTC&characterEnconding=utf-8";
con = DriverManager.getConnection(url,"root","123456");
//操作数据
String sql = "select * from user where username = '"+name+"' and password = '"+passwd+"';";
stmt = con.createStatement();
rs = stmt.executeQuery(sql);
// 判断返回的结果
if (rs.next()) {
// 登录成功
int id = rs.getInt("id");
String u_name = rs.getString("username");
String u_pwd = rs.getString("password");
String email = rs.getString("email");
// System.out.println(id + " : " + u_name + " : " + u_pwd + " : " + email);
System.out.println("登录成功!");
} else {
// 登录失败
System.out.println("登录失败! 用户名或密码错误!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//释放资源
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
con = null;
}
}
}
}
结果:
请输入用户名
lisi
请输入密码
123
登录成功!
由于对用户的输入没有进行充分的检查而SQL又是拼接而成,在用户输入参数时,在参数中添加一些SQL 关键字,达到改变SQL运行结果的目的。
案例一:
输入用户时: zhangsan’ or ‘1’=’1 password 随意
代码中sql语句进行拼接
select * from user where username ='zhangsan' or '1'='1' and password ='';
由于 and 优先级 执行 高于 or,导致不需要任何密码都能登录成功
请输入用户名
lisi' or '1'='1
请输入密码
00000000
登录成功!
案例二:
用户输入 username: zhangsan’ – password 随意
代码中sql语句进行拼接
select * from user where username ='zhangsan' -- ' and password ='' ;
在SQL添加 – 是mysql的注释
请输入用户名
lisi' --
请输入密码
111111
登录成功!
方式二:(推荐使用)
通过数据库连接对象获取操作数据库sql语句的对象PreparedStatement
String sql = "select * from user where username = ? and password = ?;";
PreparedStatement pstmt = con.prepareStatement(sql);
pstmt.setString(1,name);
pstmt.setString(2,passwd);
解析:
//表示给第一个?设置一个字符串类型的值
pstmt.setString(1,name);
代码二:
import java.sql.*;
import java.util.Scanner;
public class JDBCTest3 {
public static void main(String[] args) {
System.out.println("请输入用户名");
String name = new Scanner(System.in).nextLine();
System.out.println("请输入密码");
String passwd = new Scanner(System.in).nextLine();
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
String url = "jdbc:mysql://localhost:3306/day04?serverTimezone=UTC&characterEnconding=utf-8";
con = DriverManager.getConnection(url,"root","123456");
String sql = "select * from user where username = ? and password = ?;";
pstmt = con.prepareStatement(sql);
pstmt.setString(1,name);
pstmt.setString(2,passwd);
rs = pstmt.executeQuery();
// 判断返回的结果
if (rs.next()) {
// 登录成功
int id = rs.getInt("id");
String u_name = rs.getString("username");
String u_pwd = rs.getString("password");
String email = rs.getString("email");
// System.out.println(id + " : " + u_name + " : " + u_pwd + " : " + email);
System.out.println("登录成功!");
} else {
// 登录失败
System.out.println("登录失败! 用户名或密码错误!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
if (pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
pstmt = null;
}
if (con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
con = null;
}
}
}
}
结果
请输入用户名
lisi
请输入密码
123
登录成功!
int count = pstmt.executeUpdate();
ResultSet rs = pstmt.executeQuery();
boolean flag = pstmt.execute();
Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象。 特别是Connection对象,它是非常稀有的资源,用完后必须马上释放,如果Connection不能及时、正确的关闭,极易导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。
无结果集释放资源
public static void release(Connection con, Statement stmt) {
if(con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
con = null;
}
if(stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
}
有结果集释放资源
public static void release(Connection con,Statement stmt,ResultSet rs) {
if(con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
con = null;
}
if(stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
release(rs);
}
public static void release(ResultSet rs) {
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
}
抽取数据库信息
driverClass=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/day04?serverTimezone=UTC&characterEncoding=utf-8
username=root
passwd=123456
解析配置文件并对上述JDBC连接数据库的步骤进行封装
import java.sql.*;
public class JDBCUtils {
private static final String DRIVERCLASS="com.mysql.cj.jdbc.Driver";
private static final String URL="jdbc:mysql://localhost:3306/day04?serverTimezone=UTC" +
"&characterEncoding=utf-8";
private static final String USERNAME="root";
private static final String PASSWD="123456";
//加载驱动
public static void loadDriver() {
try {
Class.forName(DRIVERCLASS);
} catch (ClassNotFoundException e) {
throw new RuntimeException("驱动加载失败");
}
}
//获取连接
public static Connection getConnection() throws SQLException {
String url = URL;
Connection con = DriverManager.getConnection(url,USERNAME,PASSWD);
return con;
}
//无结果集释放资源
public static void realease(Connection con, Statement stmt) {
if(stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
con = null;
}
}
//有结果集释放资源
public static void realease(Connection con, Statement stmt,ResultSet rs) {
if(stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
stmt = null;
}
if(con != null) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
con = null;
}
realease(rs);
}
public static void realease(ResultSet rs) {
if(rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
rs = null;
}
}
}
测试:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class JDBCTest5 {
public static void main(String[] args) {
Connection con = null;
PreparedStatement pstmt = null;
try {
con = JDBCUTils2.getConnection();
String sql = "update user set username = ?,password = ?,email = ? where id = ?;";
pstmt = con.prepareStatement(sql);
pstmt.setString(1,"jiuba");
pstmt.setString(2,"888");
pstmt.setString(3,"jiuba@baidu.com");
pstmt.setString(4,"2");
int count = pstmt.executeUpdate();
System.out.println(count);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCUTils2.realease(con,pstmt);
}
}
}
结果
1