JDBC的工作原理
简要概述
JDBC API 允许用户访问任何形式的表格数据,尤其是存储在关系数据库中的数据。
执行流程:
- 连接数据源,如:数据库。
- 为数据库传递查询和更新指令。
- 处理数据库响应并返回的结果。
主要接口和类:
-
DriverManager类
依赖的数据库不同,管理JDBC驱动
-
Connection接口
负责连接数据库并担任传送数据的任务
-
Statement接口
由Connection产生、负责执行SQL语句
-
ResultSet接口
负责保存Statement执行后产生的结果查询
JDBC驱动说明
- 根据你选择的不同数据库去下载相应的jar包导入工程
Connection连接接口
与特定数据库的连接(会话)。在连接的上下文中执行 SQL 语句并返回结果。
//Class会触发类的加载,从而完成驱动的注册
Class.forName("com.mysql.jdbc.Driver");
String URL = "jdbc:mysql://localhost:3306/mysql";
String USERNAME = "root";
String PASSWORD = "123456";
Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
Java通过java.sql.DriverManager来管理所有数据库的驱动注册,所以如果想要建立数据库连接需要先在java.sql.DriverManager中注册registerDriver对应的驱动类,然后调用getConnection方法才能连接上数据库。
Java通过java.sql.DriverManager来管理所有数据库的驱动注册,所以如果想要建立数据库连接需要先在java.sql.DriverManager中注册对应的驱动类,然后调用getConnection方法才能连接上数据库。
java.sql.DriverManager.getConnection(xx)其实就是间接的调用了java.sql.Driver类的connect方法实现数据库连接的。数据库连接成功后会返回一个叫做java.sql.Connection的数据库连接对象,一切对数据库的查询操作都将依赖于这个Connection对象。
Statement语句对象
方法名 | 说明 |
---|---|
ResultSet executeQuery(String sql) | 执行SQL查询并获取到ResultSet对象 |
int executeUpdate(String sql) | 可以执行插入、删除、更新等操作,返回值是执行该操作所影响的行数 |
boolean execute(String sql) | 可以执行任意sQL语句,然后获得一个布尔值,表示是否返回Resultset |
ResultSet结果集对象
方法名 | 说明 |
---|---|
boolean next() | 将游标从当前位置向下移动一行 |
boolean previous() | 游标从当前位置向上移动一行 |
void close() | 关闭ResultSet对象 |
int getInt(int colIndex) | 以int形式获取结果集当前行指定列号值 |
int getInt(String colLabel) | 以int形式获取结果集当前行指定列名值 |
float getFloat(int colIndex) | 以float形式获取结果集当前行指定列号值 |
float getFloat(String colLabel) | 以float形式获取结果集当前行指定列名值 |
String getString(int colIndex) | 以string形式获取结果集当前行指定列号值 |
String getString(String colLabel) | 以string形式获取结果集当前行指定列名值 |
PreparedStatement预编译语句对象
PreparedStatement 是一个特殊的Statement对象,如果我们只是来查询或者更新数据的话,最好用PreparedStatement代替Statement,因为它有以下有点:
-
简化Statement中的操作
-
提高执行语句的性能
-
可读性和可维护性更好
-
安全性更好。
-
使用PreparedStatement能够预防SQL注入攻击,所谓SQL注入,指的是通过把SQL命令插入到Web表单提交或者输入域名或者页面请求的查询字符串,最终达到欺骗服务器,达到执行恶意SQL命令的目的。注入只对SQL语句的编译过程有破坏作用,而执行阶段只是把输入串作为数据处理,不再需要对SQL语句进行解析,因此也就避免了类似select * from user where name='aa' and password='bb' or 1=1的sql注入问题的发生。
Statement 和 PreparedStatement之间的关系和区别.
- 关系:PreparedStatement继承自Statement,都是接口
- 区别:PreparedStatement可以使用占位符,是预编译的,批处理比Statement效率高
创建PreparedStatement
创建一个PreparedStatement PreparedStatement对象的创建也同样离不开 DriverManger.getConnect()对象,因为它也是建立在连接到数据库之上的操作。
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/db_test?useSSL=false";
String username = "root";
String password = "root";
Connection connection = DriverManager.getConnection(url, username, password);
String sql = "update user set username=? where id = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
设置入参
preparedStatement.setString(1, "user");
preparedStatement.setInt(2, 1001);
执行更新
int result = preparedStatement.executeUpdate();
System.out.printf("更新记录数:"+result+"\n");//更新记录数:1
实例
public class Demo05 {
public static void main(String[] args) {
Demo05 demo05 = new Demo05();
Scanner scanner = new Scanner(System.in);
System.out.println("请输入账号");
String name= scanner.nextLine();
System.out.println("请输入密码");
scanner.next();
String pwd = scanner.nextLine();
boolean login = demo05.login(name, pwd);
System.out.println("登录:"+login);
}
public boolean login(String name,String pwd){
Connection connection = null;
PreparedStatement ps = null;
ResultSet resultSet = null;
try{
//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//连接SQL库
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mysqltest?useSSL=false", "root", "5863385");
//创建SQL语句
String sql = "SELECT * FROM student WHERE studentNo = ? AND loginPwd= ? ";
//创建预编译语句对象
ps = connection.prepareStatement(sql);
//语句赋值
ps.setString(1,name);
ps.setString(2,pwd);
resultSet = ps.executeQuery();
if (resultSet.next()){
return true;
}else{
return false;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
throw new RuntimeException("SQL异常");
} catch (ClassNotFoundException e) {
e.printStackTrace();
throw new RuntimeException("Class找不到");
} finally {
try {
resultSet.close();
ps.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException("关闭异常");
}
}
}
}