文章目录
JDBC 是什么?
Java Database Connectivity | Java 数据库连接 技术
通过 JDBC
提供的方法 可以发送字符串
类型的 SQL语句
到DBMS
(数据库管理系统 比如 MySQL Oracle), 并且获取到语句的执行结果。
从而实现 对 数据库 数据的 CRUD
( 增删改查 )
JDBC
由 Java语言的规范(接口) 和 各个数据库厂商的实现驱动(jar) 组成
JDBC
是一种典型的面向接口
编程
导入JDBC jar包
mysql版本 | 推荐驱动版本 | 备注 |
mysql 5.5.x | 5.0.x | com.mysql.jdbc.Driver |
mysql 5.7.x | 5.1.x | com.mysql.jdbc.Driver |
msyql 8.x | 8.0.x | 建议: 8.0.25+省略时区设置com.mysql.cj.jdbc.Driver |
Java工程导入依赖
1. 项目创建lib文件夹
2. 导入驱动依赖jar包
3. jar包右键-添加为项目依赖
一、JDBC的核心API和使用路线
JDBC 技术组成:
- JDK下JDBC规范接口 , 存储在 java.sql 和 javax.sql 包中的API
为了项目代码的可移植性,可维护性,SUN公司从最初就制定了Java程序连接各种数据库的统一接口规范。这样的话,不管是连接哪一种DBMS软件,Java代码可以保持一致性。
- 各个数据库厂商提供的驱动jar包
因为各个数据库厂商的DBMS软件各有不同,那么内部如何通过sql实现增、删、改、查等管理数据,只有这个数据库厂商自己更清楚,因此把接口规范的实现交给各个数据库厂商自己实现。
- jar包是什么?
java程序打包的一种压缩包格式,可以将这些jar包引入项目中,就可以使用这个java程序中类和方法以及属性了!
核心类和接口
DriverManager
获取连接;
接着建立连接;
PreparedStatement
(最常用)发送sql
语句;
若是查询操作,则对应的查询结果放在Result
中。
DriverManager
- 将第三方数据库厂商的实现驱动
jar
注册到程序中 - 可以根据数据库连接信息获取
connection
- 将第三方数据库厂商的实现驱动
- Connection [建立连接]
- 和数据库建立的连接,在连接对象上,可以多次执行数据库CRUD动作
- 可以获取
statement
和preparedstatement
,callablestatement
对象
- Statement【适用静态sql路线 没有动态值的】
PreparedStatement【预编译sql 有动态值语句】
CallableStatement- 具体发送
SQL
语句到数据库管理软件的对象 - 不同发送方式稍有不同!
preparedstatement
使用为重点!
- 具体发送
- Result【对查询语句才有】(查询的结果)
- 面向对象思维的产物 (抽象成数据库的查询结果表)
- 存储DQL查询数据库结果的对象
- 需要我们进行解析,获取具体的数据库数据
API 使用路线
JDBC基本使用步骤分析(6步)
- 注册驱动【依赖的jar包 进行安装】
- 获取连接【connection建立连接】
- 创建发送sql语句对象【statement 创建发送sql语句的statement】
- 发送sql语句,并获取返回结果【statement发送sql语句到数据库 并且取得返回结构】
- 结果集解析【将result结果解析出来】
- 资源关闭【释放resultset、statement、connection】
二、基于 statement 演示 查询
- 准备数据库数据
CREATE DATABASE jdbc_test;
USE jdbc_test;
CREATE TABLE t_user(
id INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户主键',
account VARCHAR(20) NOT NULL UNIQUE COMMENT '账号',
PASSWORD VARCHAR(64) NOT NULL COMMENT '密码',
nickname VARCHAR(20) NOT NULL COMMENT '昵称');
INSERT INTO t_user(account,PASSWORD,nickname) VALUES
('root','123456','经理'),('admin','666666','管理员');
- 代码实现
// @Description: 使用statement查询t_user表下,全部数据
// 1. 注册驱动
DriverManager.registerDriver(new Driver());
// 2. 建立连接
/*
* java连接数据库肯定是调用某个方法,方法也需要填入数据库的基本信息:
* 数据库ip地址:127.0.0.1
* 数据库端口号:3306
* 账号:root
* 密码:root
* 连接数据库的名称:jdbc_test
*
* DriverManager.getConnection的参数
* 参数1 url:
* jdbc:数据库厂商名://ip地址:port/数据库名
* jdbc:mysql://127.0.0.1:3306/jdbc_test
* */
//java.sql 接口 = 实现类
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc_test",
"root", "root");
// 3. 创建statement对象
Statement statement = connection.createStatement();
// 4. 发送sql
String sql = "SELECT * FROM t_user";
ResultSet resultSet = statement.executeQuery(sql);
// 5. 接收 解析返回的结果集
while (resultSet.next()) {
int id = resultSet.getInt("id");
String account = resultSet.getString("account");
String password = resultSet.getString("password");
String nickname = resultSet.getString("nickname");
//输出列的结果
System.out.println(id + "--" + account + "--" + password + "--" + nickname);
}
// 6. 关闭资源【先打开的后关】
resultSet.close();
statement.close();
connection.close();
三、基于 statement 查询的改进与问题
需求:模拟登录 输入用户名/密码
//1.输入账号和密码
Scanner scanner = new Scanner(System.in);
String account = scanner.nextLine();
String password = scanner.nextLine();
scanner.close();
//方法1:DriverManager.registerDriver(new Driver());调用两次。不用
//方法2:new Driver() 频繁修改不优雅
//方法3.使用反射 注册一次驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//获取连接
//省略写法: jdbc:mysql://localhost:3306/test = jdbc:mysql:///test
Connection connection = DriverManager.getConnection("jdbc:mysql:///jdbc_test", "root", "root");
//固定方法固定剂
//创建statement
Statement statement = connection.createStatement();
//执行SQL语句 [动态SQL语句,需要字符串拼接]
String sql = "select * from t_user where account = '"+account+"' and password = '"+password+"' ;";
/**
* ResultSet 结果集对象 = executeQuery(DQL语句)
* int响应行数 = executeUpdate(非DQL语句)
*/
ResultSet resultSet = statement.executeQuery(sql);
//ResultSet == navicat
/**
* 1.需要理解ResultSet的数据结构和navicat查询出来的是一样!
* 2.有一个光标指向的操作数据行,默认指向第一行的上边!我们需要移动光标,指向行,在获取列即可!
* boolean = next()
* false: 没有数据,也不移动了!
* true: 有更多行,并且移动到下一行!
* 推荐:推荐使用if 或者 while循环,嵌套next方法,循环和判断体内获取数据!
* if(next()){获取列的数据!} || while(next()){获取列的数据!}
*
*3.获取当前行列的数据!
* get类型(int columnIndex | String columnLabel)
* 列名获取 //lable 如果没有别名,等于列名, 有别名label就是别名,他就是查询结果的标识!
* 列的角标 //从左到右 从1开始! 数据库全是从1开始!
*/
//进行结果集对象解析
if (resultSet.next()){
//只要向下移动,就是有数据 就是登录成功!
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
//关闭资源
resultSet.close();
statement.close();
connection.close();
存在的问题:
- SQL语句需要字符串拼接,比较麻烦
- 只能拼接字符串类型,其他的数据库类型无法处理
- 可能发生注入攻击
四、基于 preparedStatement 方式优化
利用preparedStatement解决上述案例注入攻击和SQL语句拼接问题!
public class PreparedStatementLoginPart {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 1. 输入用户名 密码
Scanner scanner = new Scanner(System.in);
String account = scanner.nextLine();
String password = scanner.nextLine();
scanner.close();
// 2. 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 3. 获取连接
Connection connection = DriverManager.getConnection("jdbc:mysql:///jdbc_test", "root", "root");
// 4.创建sql对象 与 sql语句
String sql = "SELECT * FROM t_user WHERE account = ? AND password = ?;" ;
PreparedStatement preparedStatement = connection.prepareStatement(sql);
// 占位符? 赋值 从左到右,从1开始
// 参数:int 占位符下角标 ; objects 占位符的值
preparedStatement.setObject(1,account);
preparedStatement.setObject(2,password);
// 5. 结果集解析
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
//只要向下移动,就是有数据 就是登录成功!
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
resultSet.close();
preparedStatement.close();
connection.close();
}
}
五、基于 preparedStatement 演示 CRUD
C 、增加数据
/**
* 插入一条用户数据!
* 账号: test
* 密码: test
* 昵称: 测试
*/
@Test
public void testInsert() throws SQLException, ClassNotFoundException {
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/jdbc_test", "root", "root");
String sql = "INSERT INTO t_user(account,password,nickname) VALUES(?,?,?);";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1,"test");
preparedStatement.setString(2,"test");
preparedStatement.setString(3,"测试");
int rows = preparedStatement.executeUpdate();
System.out