JDBC简介
JDBC概念
- JDBC就是使用Java语言操作关系型数据库的一套API
- 全称:(Java DataBase Connectivity)Java数据库连接
JDBC本质:
- 官方(Sun公司)定义的一套操作所有关系型数据库的规则,即接口
- 各个数据库厂商去实现这套接口,提供数据库驱动jar包
- 我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类
JDBC好处:
- 各数据库厂商使用相同的接口,Java代码不需要针对不同数据库分别开发
- 可随时替换底层数据库,访问数据库的Java代码基本不变
MySQL
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lHAYbdj0-1647509511246)(/upload/2022/03/Snipaste_2022-03-16_10-38-20-96495553dee446c7b9991a9420d18531.png)]
JDBC快速入门
- 创建工程,导入驱jar包
mysql-connector-java-8.0.27.jar
- 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
- 获取连接
Connection conn = DriverManager.getConnection(url,username,password);
- 定义SQL语句
String sql "update...";
- 获取执行SQL对象
Statement stmt conn.createStatement();
- 执行SQL
stmt.executeUpdate(sql);
- 处理返回结果
- 释放资源
JDBC API详解
DriverManager(驱动管理类)
作用:
- 注册驱动
- 获取数据库连接
具体:
- 注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
那么为什么上面这段代码就可以实现驱动的注册呢,查看源代码Driver类的源码发现,底层调用的仍然是DriverManager
类中的registerDriver
方法。
查看Driver类源码
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
- 获取连接
static Connection getConnection(String url, String user, String password)
- 参数
- url:连接路径
语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?参数键值对1&参数键值对2…
例子:jdbc:mysql://127.0.0.1:3306/db1
细节:
如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称?参数键值对
; 配置useSSL=false参数,禁用安全连接方式,解决警告提示 - user:用户名
- password:密码
- url:连接路径
- 参数
其他
- MySQL 5之后的驱动包,可以省略注册驱动的步骤
- 自动加载jar包中META-INF/services/java.sql.Driver文件中的驱动类
Connection(数据库连接对象)
作用:
- 获取执行SQL的对象
- 管理事务
具体:
-
获取执行SQL的对象
- 普通执行SQL对象
Statement createStatement()
- 预编译SQL的执行SQL对象:防止SQL注入
PreparedStatement prepareStatement(sql)
- 执行存储过程的对象(不需要具体理解)
CallableStatement prepareCall(sql)
- 普通执行SQL对象
-
事务管理
- MySQL事务管理
开启事务:BEGIN; / START TRANSACTION;
提交事务:COMMIT;
回滚事务:ROLLBACK;
MySQL默认自动提交事务- JDBC事务管理:Connection接口中定义了3个对应的方法
开启事务:setAutoCommit(boolean autoCommit):true为自动提交事务;false为手动提交事务,即为开启事务
提交事务:commit()
回滚事务:rollback()
Statement
作用:
执行SQL语句
具体:
执行SQL语句
int executeUpdate(String sql) throws SQLException;
执行DML、DDL语句
返回值:(1)DML语句影响的行数;(2)DDL语句执行后,执行成功也可能返回0
ResultSet executeQuery(String sql) throws SQLException;
执行DQL语句
返回值:ResultSet结果集对象
ResultSet(结果集对象)
作用:
- 封装了DQL查询语句的结果
ResultSet stmt.executeQuery(sql);
执行DQL语句,返回ResultSet对象 - 获取查询结果
boolean next()
(1)将光标从当前位置向前移动一行
(2)判断当前行是否为有效行
返回值:
true:有效行,当前行有数据
false:无效行,当前行没有数据
XXX getXxx(参数):获取数据
xxx:数据类型
- 如:int getInt(参数);String getString(参数)
参数:
- int:列的编号,从1开始
- String:列的名称
使用步骤
- 游标向下移动一行,并判断该行否有数据:next()
- 获取数据:getXxx(参数)
// 循环判断游标是否是最后一行末尾
while(res.next()) {
// 获取数据
res.getXxx(参数);
}
PreparedStatement
作用:
- 预编译SQL语句并执行:预防SQL注入问题
- SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法。
具体:
- 预编译SQL并执行SQL语句
- 获取PreparedStatement对象
// SQL语句中的参数值,使用 ? 占位符替代 String sql = "select * from user where username = ? and password = ?"; // 通过 Connection 对象获取,并传入对应的SQL语句 PreparedStatement pstmt = conn.prepareStatement(sql);
- 设置参数
PreparedStatement对象:setXxx(参数1,参数2):给 ? 赋值 Xxx:数据类型;如 setInt(参数1,参数2) 参数: 参数1: ?的位置编号,从1开始 参数2: ?的值
- 执行SQL
executeUpdate(); / executeQuery();
不需要再传递SQL
好处:
PreparedStatement好处:
- 预编译SQL,性能更高
- 防SQL注入:将敏感字符进行转义
这里要注意要想在MySQL中使用预编译功能来提高执行SQL的性能,我们需要手动开启预编译功能,即在连接MySQL的url中指定如下参数
PreparedStatement预编译功能开启:useServerPrepStmts=true
配置MySQL执行日志(重启MySQL服务后生效)
log-output=FILE
general-log=1
general_log_file="D:\mysql.log"
slow-query-log=1
slow_query_log_file="D:\mysql_slow.log"
long_query_time=2
首先明白SQL的执行过程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d6fHSuQ6-1647509511248)(/upload/2022/03/Snipaste_2022-03-17_08-57-07-a201aaf8278c479f82b908cc0f07c6a8.png)]
PreparedStatement原理:
- 在获取 PreparedStatement 对象时,将SQL语句发送给MySQL服务器
进行检查,编译(这些步骤很耗时) - 执行的时候就不用再进行这些步骤了,速度更快
- 如果SQL模板一样,则只需要进行一次检查、编译
Spring JDBC
简介:
Spring框架对JDBC的简单封装。提供了一个 JDBCTemplate 对象简化JDBC的开发
步骡:
- 导入jar包
- 创建JdbcTemplate对象。依赖于数据源 DataSource
JdbcTemplate template = new JdbcTemplate(ds);
- 调用JdbcTemplate的方法来完成CRUD的操作
- update():执行DML语句。增、删、改语句
- queryForMap():查询结果将结果集封装为Map集合,将列名作为key,将值作为value,将这条记录封装为一个Map集合
注意:这个方法查询的结果集长度只能是1 - queryForList():查询结果将结果集封装为List集合
注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中 - query():查询结果,将结果封装为JavaBean对象
query的参数:RowMapper- 一般我们使用
BeanPropertyRowMapper
实现类,可以完成数据到JavaBean的自动封装 - new BeanPropertyRowMapper<类型>(类型.class)
- 一般我们使用
- queryForObject():查询结果,将结果封装为对象。一般用于聚合函数的查询。