JDBC概述
什么是JDBC
- JDBC(Java Data Base Connectivity) 是Java访问数据库的标准规范。是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。
JDBC原理
-
JDBC是接口,驱动是接口的实现,没有驱动将无法完成数据库连接,从而不能操作数据库!每个数据库厂商都需要提供自己的驱动,用来连接自己公司的数据库,也就是说驱动一般都由数据库生成厂商提供。
-
总结:
JDBC就是由sun公司定义的一套操作所有关系型数据库的规则(接口),而数据库厂商需要实现这套接口,提供数据库驱动jar包,我们可以使用这套接口编程,真正执行的代码是对应驱动包中的实现类。
JDBC开发
API使用: 1.注册驱动
- JDBC规范定义驱动接口: java.sql.Driver
- MySql驱动包提供了实现类: com.mysql.jdbc.Driver
加载注册驱动的方式 | 描述 |
---|---|
Class.forName(数据库驱动实现类) | 加载和注册数据库驱动,数据库驱动由数据库厂商MySql提供”com.mysql.jdbc.Driver” |
- 代码示例
public class JDBCDemo01 {
public static void main(String[] args) throws ClassNotFoundException {
//1.注册驱动
// forName 方法执行将类进行初始化
Class.forName("com.mysql.jdbc.Driver");
}
}
复制代码
- 注:
从JDBC3开始,目前已经普遍使用的版本。可以不用注册驱动而直接使用。 Class.forName这句话可以省略。
API使用: 2.获得连接
- Connection接口,代表一个连接对象,具体的实现类由数据库的厂商实现
- 使用DriverManager类的静态方法,getConnection可以获取数据库的连接
获取连接的静态方法 | 说明 |
---|---|
Connection getConnection(String url, String user, String password) | 通过连接字符串和用户名,密码来获取数据库连接对象 |
- 1) getConnection方法3个连接参数说明
连接参数 | 说明 |
---|---|
user | 登录用户名 |
password | 登录密码 |
url | mySql URL的格式 jdbc:mysql://localhost:3306/db4 |
- 2) 对URL的详细说明
jdbc:mysql://localhost:3306/db4?characterEncoding=UTF-8
- JDBC规定url的格式由三部分组成,每个部分中间使用冒号分隔。
- 第一部分是协议jdbc,这是固定的;
- 第二部分是子协议,就是数据库名称,连接mysql数据库,第二部分当然是mysql了;
- 第三部分是由数据库厂商规定的,我们需要了解每个数据库厂商的要求,mysql的第三部分分别由数据库服务器的IP地址(localhost)、端口号(3306),以及要使用的数据库名称组成。
API 使用: 3.获取语句执行平台
- 通过Connection的createStatement方法获取sql语句执行对象
Connection接口中的方法 | 说明 |
---|---|
Statement createStatement() | 创建SQL语句执行对象 |
- Statement:代表一条语句对象,用于发送SQL语句给服务器,用于执行静态SQL语句并返回它所生成结果的对象。
Statement类常用方法 | 说明 |
---|---|
int executeUpdate(String sql); | 执行insert update delete语句。返回int类型,代表受影响的行数 |
ResultSet executeQuery(String sql); | 执行select语句,返回ResultSet结果集对象 |
API 使用: 4.处理结果集
- 只有在进行查询操作的时候,才会处理结果集
ResultSet接口
- 作用:封装数据库查询的结果集,对结果集进行遍历,取出每一条记录。
ResultSet接口方法 | 说明 |
---|---|
boolean next() | 1) 游标向下一行 2) 返回boolean类型,如果还有下一条记录,返回true,否则返回 false |
xxx getXxx( String or int) | 1) 通过列名,参数是String类型。返回不同的类型 2) 通过列号,参数是整数,从1开始。返回不同的类型 |
API 使用: 5.释放资源
1) 需要释放的对象:ResultSet结果集,Statement语句,Connection连接
2) 释放原则:先开的后关,后开的先关。ResultSet ==> Statement ==> Connection
3) 放在哪个代码块中:finally块
- 与IO流一样,使用后的东西都需要关闭!关闭的顺序是先开后关, 先得到的后关闭,后得到的先关闭
步骤总结
- 获取驱动(可以省略)
- 获取连接
- 获取Statement对象
- 处理结果集(只在查询时处理)
- 释放资源
JDBC实现增删改查
JDBC工具类
- 什么时候自己创建工具类?
- 如果一个功能经常要用到,我们建议把这个功能做成一个工具类,可以在不同的地方重用。
- “获得数据库连接”操作,将在以后的增删改查所有功能中都存在,可以封装工具类JDBCUtils。提供获取连接对象的方法,从而达到代码的重复利用。
- 工具类包含的内容
-
- 可以把几个字符串定义成常量:用户名,密码,URL,驱动类
-
- 得到数据库的连接:getConnection()
-
- 关闭所有打开的资源:
-
DML操作
插入记录
- 解决插入中文乱码问题
// jdbc:mysql://localhost:3306/db4?characterEncoding=UTF-8
// characterEncoding=UTF-8 指定字符的编码、解码格式。
复制代码
- 代码示例
/**
* 插入数据
* @throws SQLException
*/
@Test
public void testInsert() throws SQLException {
//1.通过工具类获取连接
Connection connection = JDBCUtils.getConnection();
//2.获取Statement
Statement statement = connection.createStatement();
//2.1 编写Sql
String sql = "insert into jdbc_user values(null,'张百万','123','2020/1/1')";
//2.2 执行Sql
int i = statement.executeUpdate(sql);
System.out.println(i);
//3.关闭流
JDBCUtils.close(connection,statement);
}
复制代码
更新记录
- 根据ID需改用户名称
/**
* 修改 id 为1 的用户名为 广坤
*/
@Test
public void testUpdate() throws SQLException {
Connection connection = JDBCUtils.getConnection();
Statement statement = connection.createStatement();
String sql = "update jdbc_user set username = '广坤' where id = 1";
statement.executeUpdate(sql);
JDBCUtils.close(connection,statement);
}
复制代码
删除记录
- 删除id为3和4的记录
/**
* 删除id 为 3 和 4的记录
* @throws SQLException
*/
@Test
public void testDelete() throws SQLException {
Connection connection = JDBCUtils.getConnection();
Statement statement = connection.createStatement();
statement.executeUpdate("delete from jdbc_user where id in(3,4)");
JDBCUtils.close(connection,statement);
}
复制代码
DQL操作
查询姓名为张百万的一条记录
public class TestJDBC02 {
public static void main(String[] args) throws SQLException {
//1.获取连接对象
Connection connection = JDBCUtils.getConnection();
//2.获取Statement对象
Statement statement = connection.createStatement();
String sql = "SELECT * FROM jdbc_user WHERE username = '张百万';";
ResultSet resultSet = statement.executeQuery(sql);
//3.处理结果集
while(resultSet.next()){
//通过列名 获取字段信息
int id = resultSet.getInt("id");
String username = resultSet.getString("username");
String password = resultSet.getString("password");
String birthday = resultSet.getString("birthday");
System.out.println(id+" "+username+" " + password +" " + birthday);
}
//4.释放资源
JDBCUtils.close(connection,statement,resultSet);
}
}
复制代码
SQL注入问题
Sql注入演示
1) 向jdbc_user表中插入两条数据
# 插入2条数据
INSERT INTO jdbc_user VALUES(NULL,'jack','123456','2020/2/24');
INSERT INTO jdbc_user VALUES(NULL,'tom','123456','2020/2/24');
复制代码
2) SQL注入演示
# SQL注入演示
-- 填写一个错误的密码
SELECT * FROM jdbc_user WHERE username = 'tom' AND PASSWORD = '123' OR '1' = '1';
复制代码
如果这是一个登陆操作,那么用户就登陆成功了。显然这不是我们想要看到的结果
问题分析
什么是SQL注入?
- 我们让用户输入的密码和SQL语句进行字符串拼接。用户输入的内容作为了SQL语句语法的一部分,改变了原有SQL 真正的意义,以上问题称为SQL注入。
如何实现的注入
- 根据用户输入的数据,拼接处的字符串
select * from jdbc_user where username = 'abc' and password = 'abc' or '1'='1'
-- name='abc' and password='abc' 为假 '1'='1' 真
-- 相当于 select * from user where true=true; 查询了所有记录
复制代码
如何解决
- 要解决SQL注入就不能让用户输入的密码和我们的SQL语句进行简单的字符串拼接。
预处理对象
PreparedStatement 接口介绍
- PreparedStatement是Statement接口的子接口,继承于父接口中所有的方法。它是一个预编译的SQL语句对象。
- 预编译:是指SQL语句被预编译,并存储在PreparedStatement对象中。然后可以使用此对象多次高效地执行该语句。
PreparedStatement特点
- 因为有预先编译的功能,提高SQL的执行效率。
- 可以有效的防止SQL注入的问题,安全性更高
获取PreparedStatement对象
- 通过Connection创建PreparedStatement对象
Connection接口中的方法 | 说明 |
---|---|
PreparedStatement prepareStatement(String sql) | 指定预编译的SQL语句,SQL语句中使用占位符?创建一个语句对象 |
PreparedStatement接口常用方法
常用方法 | 说明 |
---|---|
int executeUpdate(); | 执行insert update delete语句 |
ResultSet executeQuery(); | 执行select语句. 返回结果集对象 Resulet |
使用PreparedStatement的步骤
1) 编写SQL语句,未知内容使用?占位:
"SELECT * FROM jdbc_user WHERE username=? AND password=?";
2) 获得PreparedStatement对象
3) 设置实际参数:setXxx( 占位符的位置, 真实的值)
4) 执行参数化SQL语句
5) 关闭资源
setXxx重载方法 | 说明 |
---|---|
void setDouble(int parameterIndex, double x) | 将指定参数设置为给定 Java double 值。 |
void setInt(int parameterIndex, int x) | 将指定参数设置为给定 Java int 值。 |
void setString(int parameterIndex, String x) | 将指定参数设置为给定 Java String 值。 |
void setObject(int parameterIndex, Object x) | 使用给定对象设置指定参数的值。 |
Statement 与 PreparedStatement的区别?
- Statement用于执行静态SQL语句,在执行时,必须指定一个事先准备好的SQL语句。
- PrepareStatement是预编译的SQL语句对象,语句中可以包含动态参数“?”,在执行时可以为“?”动态设置参数值。
- PrepareStatement可以减少编译次数提高数据库性能。
JDBC 控制事务
- 之前我们是使用MySQL的命令来操作事务。接下来我们使用JDBC来操作银行转账的事务。
事务相关API
- 我们使用Connection中的方法实现事务管理
方法 | 说明 |
---|---|
void setAutoCommit(boolean autoCommit) | 参数是true或false如果设置为false,表示关闭自动提交,相当于开启事务 |
void commit() | 提交事务 |
void rollback() | 回滚事务 |
开发步骤
- 获取连接
- 开启事务
- 获取到 PreparedStatement , 执行两次更新操作
- 正常情况下提交事务
- 出现异常回滚事务
- 最后关闭资源
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END