JDBC知识点整理
2021/7/16 23:41:08
本文主要是介绍JDBC知识点整理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
JDBC入门
1 JDBC:Java DataBase Connectivity
1.1JDBC的概念
JDBC规范定义接口,具体的实现由各大数据库厂商来实现。
JDBC是Java访问数据库的标准规范,真正的怎么操作数据库还需要具体的实现类,也就是数据库驱动。每个数据库厂商根据自家数据库的驱动。所以只需要会调用JDBC接口中的方法即可,数据库驱动由数据库厂商提供
- 使用JDBC的好处:
- 程序员如果要开发访问数据库的程序,只需要会调用JDBC接口中的方法即可,不用关注类如何实现的。
- 使用同一套Java代码,进行少量的修改就可以访问其他JDBC支持的数据库。
- 代码不依赖于任何的数据库
1.1.2 使用JDBC开发使用的包
会使用到的包 | 说明 |
---|---|
java.sql | 所有与JDBC访问数据库相关的接口和类 |
javax.sql | 数据库扩展,提供数据库额外的功能。 |
数据库的驱动 | 由各大数据库厂商提供,需要额外去下载,是对JDBC接口实现的类 |
1.2JDBC的核心API
接口或类 | 作用 |
---|---|
DriverManager类 | 1. 管理和注册数据库驱动;2. 得到数据库连接对象 |
Connection 接⼝ | ⼀个连接对象,可⽤于创建 Statement 和 PreparedStatement对象 |
Statement 接⼝ | ⼀个 SQL 语句对象,⽤于将 SQL 语句发送给数据库服务器。 |
PreparedStatement 接⼝ | ⼀个 SQL 语句对象,是 Statement 的⼦接⼝ |
ResultSet 接⼝ | ⽤于封装数据库查询的结果集,返回给客户端 Java 程序 |
1.3加载和注册驱动
加载和注册驱动的⽅法 | 描述 |
---|---|
Class.forName(数据驱动实现类) | 加载和注册数据库驱动,数据库驱动由数据库厂商实现; MySQL ⼚商: “com.mysql.jdbc.Driver” |
public class Demo1 { public static void main(String[] args) throws ClassNotFoundException { //抛出类找不到的异常,注册数据库驱动 Class.forName("com.mysql.jdbc.Driver"); } }
从JDBC3开始,目前已经普遍使用的版本,可以不用注册驱动而直接使用,Class.forName这句话可以省略
2.DriverManager类
2.1DriverManager作用
- 管理和注册驱动
- 创建数据库的连接
2.2类中的方法
DriverManager类中的静态方法 | 描述 |
---|---|
Connection getConnection(String url, String user,String password) | 通过连接字符串,⽤户名,密码来得到数据库的连接对象 |
Connection getConnection (String url, Properties info) | 通过连接字符串,属性对象来得到连接对象 |
2.3使用JDBC连接数据库的四个参数
JDBC连接数据库的四个参数 | 说明 |
---|---|
⽤户名 | 登录的⽤户名 |
密码 | 登录的密码 |
连接字符串 URL | 不同的数据库 URL 是不同的,mysql 的写法jdbc:mysql://localhost:3306/数据库[?参数名=参数值] |
驱动类的字符串名 | com.mysql.jdbc.Driver |
2.4连接数据库的URL地址格式
- 协议名:子协议://服务器名或IP地址:端口号/数据库名?参数=参数值
2.4.1MySQL写法
URL用于标识数据库的位置,程序员通过URL地址
JDBC程序连接哪个数据库,URL的写法为:
jdbc:mysql://localhost:3306/test?参数=参数值
注:jdbc:协议;
mysql:子协议;
localhost:3306: 主机:端口
test:子协议
2.4.2MySQL中可以简写
前提:必须是本地服务器,端口号是3306
jdbc:mysql:///数据库名
2.4.3乱码的处理
如果数据库出现乱码,可以指定参数:?characterEncoding=utf8,表示让数据库以UFT-8编码来处理数据。
jdbc:mysql://localhost:3306/数据库?characterEncoding=utf8
3 Connection接口
流程:
- 导入jar包
- 加载驱动类
Class.forName(“com.mysql.jdbc.Driver”);
Class.forName(“com.mysql.cj.jdbc.Driver”);
3.1Connection作用
Connection接口,具体的实现类由数据库的厂商实现,代表一个连接对象。
3.2Connection方法
Connection接口中的方法:
Statement createStatement() -- 创建一条SQL语句对象
4 Statement接口
4.1 JDBC访问数据库的步骤
- 注册和加载驱动(可以省略)
- 获取连接
- Connection获取Statement对象
- 使用Statement对象执行SQL语句
- 返回结果集
- 释放资源
4.2 Statement作用
代表一条语句对象,用于发送SQL语句给服务器,用于执行静态SQL语句并返回它所生成结果的对象。
4.3 Statement中的方法
Statement接口中的方法 | 描述 |
---|---|
int executeUpdate(String sql) | 用于发送DML语句,增删改的操作,insert、update、delete 参数:SQL语句 返回值:返回对数据库影响的行数 |
ResultSet executeQuery(String sql) | 用于发送DQL语句,执行查询的操作select 参数:SQL语句 返回值:查询的结果集 |
4.4释放资源
- 需要释放的对象:ResultSet结果集,Statement语句,Connection连接
- 释放原则:先开的后关,后开的先关。ResultSet -> Statement -> Connection
- 放在哪个代码块中:finally块
4.5DDL操作
步骤:
- 创建连接对象
- 创建Statement语句对象
- 执行SQL语句:execute(sql)
- 返回影响的行数
- 释放资源
4.6DML操作
步骤:
- 创建连接对象
- 创建Statement语句对象
- 执行SQL语句:executeUpdate(sql)
- 返回影响的行数
- 释放资源
4.7执行DQL操作
-
作用:封装数据库查询的结果集,对结果集进行遍历,取出每一条记录
-
接口中的方法
ResultSet 接⼝中的⽅法 | 描述 |
---|---|
boolean next() | 1. 游标向下移动 1 ⾏;2. 返回 boolean 类型,如果还有下⼀条记录,返回 true,否则返回 false |
数据类型 getXxx() | 1. 通过字段名,参数是 String 类型。返回不同的类型;2. 通过列号,参数是整数,从 1 开始。返回不同的类型 |
注:java.sql.Date、Time、Timestamp(时间戳),三个共同⽗类是:java.util.Date
4.7.3 需求
确保数据库中有3条以上的记录,查询所有的学员信息
- 步骤:
- 得到连接对象
- 得到语句对象
- 执行SQL语句得到结果集ResultSet对象
- 循环遍历取出每一条记录
- 输出的控制台上
- 释放资源
4.7.4关于ResultSet 接口中的注意事项
- 如果光标在第一行之前,使用rs.getXXX()获取列值,报错:Before start of result set
- 如果光标在最后一行,使用rs.getXXX()获取列值,报错:After end of result set
- 使用完毕以后要关闭结果集ResultSet,再关闭Statement,再关闭Connection
上述知识要点整合代码: import java.sql.*; public class JDBCDemo01 { public static void main(String[] args) { try { //可能出现的异常:ClassNotFoundException /*原因: * 1.java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Drive 类名写错 * 2.jar包未导入 * */ Class.forName("com.mysql.cj.jdbc.Driver"); //3.可能出现的异常:获得数据库连接 /*SQLException * 原因:1.jdbc:mysql: 其中任何一段字符串写错, ip地址协议错误 * 2. Unknown database xxxx 数据库名字错误 找不到这个数据库 * 3.SQLException: Access denied for user 'roo'@'localhost' (using password: YES) 数据库用户名或密码错误 * com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure localhost:330 * 原因:端口错误,防火墙阻拦 *ip地址出错,不会抛出异常,程序会阻塞,一直尝试连接 * */ String url = "jdbc:mysql://localhost:3306/java2106"; Connection connection = DriverManager.getConnection(url,"root","123456"); //System.out.println(connection); //4.获得执行SQL语句的Statement对象 Statement statement = connection.createStatement(); //执行DDL 通常用execute /*String sql = "create table test01(id int(6) PRIMARY KEY)"; boolean execute = statement.execute(sql); System.out.println(execute);*/ /*//执行DML 通常用executeUpdate 如果增删改成功则返回1,增删改失败则返回0 String sql = "update test01 set id = 1"; int i = statement.executeUpdate(sql); System.out.println(i);*/ //5.执行DQL获得 ResultSet String sql = "select * from emp"; //执行可能发生的异常SQLSyntaxErrorException 一般是sql语句出现异常,根据具体信息修改异常 ResultSet rs = statement.executeQuery(sql); //处理结果集 rs.next() boolean 移动到下一个位置,判断是否存在字段,如果存在则返回true while (rs.next()){ int empno = rs.getInt("empno"); String ename = rs.getString("ename"); Date hiredate = rs.getDate("hiredate"); System.out.println(empno + " " + ename + " " + hiredate); } //上述代码使得next()指向了结果集的最后行,再下一个则会超出范围 //SQLException: After end of result set /*int no = rs.getInt("empno"); String name = rs.getString("ename"); Date hireDate = rs.getDate("hiredate"); System.out.println(no + name + hireDate);*/ //关闭资源 rs.close(); statement.close(); connection.close(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException throwables) { throwables.printStackTrace(); } } }
一些注意事项整理 import java.sql.*; public class JDBCDemo02 { public static void main(String[] args) { try { Connection connection = JDBCUtils.getConnection(); //4.获得执行SQL语句的Statement对象 Statement statement = connection.createStatement(); String sql = "select * from emp"; ResultSet rs = statement.executeQuery(sql); //处理结果集 rs.next() boolean 移动到下一个位置,判断是否存在字段,如果存在则返回true while (rs.next()){ /*int empno = rs.getInt("empno"); String ename = rs.getString("ename"); Date hiredate = rs.getDate("hiredate"); System.out.println(empno + " " + ename + " " + hiredate);*/ Emp emp = new Emp(); emp.setEmpno(rs.getInt("empno")); } //上述代码使得next()指向了结果集的最后行,再下一个则会超出范围 //SQLException: After end of result set /*int no = rs.getInt("empno"); String name = rs.getString("ename"); Date hireDate = rs.getDate("hiredate"); System.out.println(no + name + hireDate);*/ //关闭资源 rs.close(); statement.close(); connection.close(); } catch (SQLException throwables) { throwables.printStackTrace(); } } }
5 数据库工具类JdbcUtils
自己创建工具类:
如果一个功能经常要用到,建议把这个功能做成一个工具类,可以再不同的地方重用。
5.1需求
出现很多的重复的代码,可以把这些公共代码抽取出来。
5.2创建类JbdcUtil包含3个方法
-
可以把几个字符串定义成常量:用户名,密码,URL,驱动类
-
得到数据库的连接:getConnection()
-
关闭所有打开的资源
close(Connection conn, Statement stmt),close(Connection conn, Statement stmt, ResultSet rs)
5.3步骤
-
得到用户从控制台上输入的用户名和密码来查询数据库
-
写一个登陆方法
a. 通过工具类得到连接
b. 创建语句对象,使用拼接字符串的方式生成SQL语句
c. 查询数据库,如果有记录则登陆成功,否则登录失败
d. 释放资源
5.4 SQL注入问题
用户输入的密码和SQL语句的字符串拼接。用户输入的内容作为SQL语句语法的一部分,改变了原有SQL真正的意义,以上问题称为SQL注入,要解决SQL注入就不能让用户输入的密码和我们的SQL语句进行简单的字符串拼接。
6 PreparedStatement接⼝
6.1继承结构与作用
接口:Statement、Wrapper
所有已知子接口:
CallableStatement
preparedStatement是Statement接口的子接口,继承于父接口中所有的方法。它是一个预编译的SQL语句。
作用:
- 因为有预先编译的功能,提高SQL的执行效率
- 可以有效的防止SQL注入的问题,安全性更高。
6.2 Connection 创建 PreparedSatement 对象
Connection 接⼝中的⽅法 | 描述 |
---|---|
PreparedStatement prepareStatement(String sql) | 指定预编译的 SQL 语句,SQL 语句中使⽤占位符?创建⼀个语句对象 |
6.3 PreparedSatement 接⼝中的⽅法
PreparedStatement 接⼝中的⽅法 | 描述 |
---|---|
int executeUpdate() | 执⾏ DML,增删改的操作,返回影响的⾏数。 |
ResultSet executeQuery() | 执⾏ DQL,查询的操作,返回结果集 |
6.4 PreparedSatement 的好处
- prepareStatement()会先将 SQL 语句发送给数据库预编译。PreparedStatement 会引⽤着
预编译后的结果。可以多次传⼊不同的参数给 PreparedStatement 对象并执⾏。减少 SQL
编译次数,提⾼效率。 - 安全性更⾼,没有 SQL 注⼊的隐患。
- 提⾼了程序的可读性。
6.5 使⽤ PreparedStatement 的步骤
- 编写 SQL 语句,未知内容使⽤?占位:“SELECT * FROM user WHERE name=? AND
password=?”; - 获得 PreparedStatement 对象
- 设置实际参数:setXxx (占位符的位置,真实的值)
- 执⾏参数化 SQL 语句
- 关闭资源
PreparedStatement 中设置参数的⽅法 | 描述 |
---|---|
void setDouble(int parameterIndex, double x) | 将指定参数设置为给定 Java double值。 |
void setFloat(int parameterIndex, float x) | 将指定参数设置为给定 Java float 值。 |
void setInt(int parameterIndex, int x) | 将指定参数设置为给定 Java int 值。 |
void setLong(int parameterIndex, long x) | 将指定参数设置为给定 Java long 值。 |
void setObject(int parameterIndex, Object x) | 使⽤给定对象设置指定参数的值。 |
void setString(int parameterIndex, String x) | 将指定参数设置为给定 Java String 值。 |
import java.sql.*; import java.util.Scanner; public class LoginDemo02 { public static void main(String[] args) throws Exception { Scanner scanner = new Scanner(System.in); System.out.println("请输入用户名:"); String username = scanner.nextLine(); System.out.println("请输入密码:"); String password = scanner.nextLine(); Connection connection = JDBCUtils.getConnection(); String sql = "select * from user where username=? and password=?"; PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setString(1,username); preparedStatement.setString(2,password); //String sql = "select * from user where username = '" + username +"' and password = '"+ password +"'"; ResultSet resultSet = preparedStatement.executeQuery(); if (resultSet.next()){ System.out.println("用户登陆成功"); }else { System.out.println("用户名或密码错误"); } resultSet.close(); preparedStatement.close(); connection.close(); } }
7 JDBC 事务的处理
7.1 API介绍
Connection 接⼝中与事务有关的⽅法 | 说明 |
---|---|
void setAutoCommit(boolean | |
autoCommit) | 参数是 true 或 false。如果设置为 false,表示关闭⾃动提交,相当于开启事务 |
void commit() | 提交事务 |
void rollback() | 回滚事务 |
7.2 开发步骤
- 获取连接
- 开启事务
- 获取到 PreparedStatement
- 使⽤ PreparedStatement 执⾏两次更新操作
- 正常情况下提交事务
- 出现异常回滚事务
- 最后关闭资源
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; public class Demo04 { public static void main(String[] args) { Connection connection = JDBCUtils.getConnection();//连接 String sql1 = "update customer set account = account - ? where cust_id = ?";//转出 String sql2 = "update customer set account = account + ? where cust_id = ?";//转入 try { //事务手动提交设置 connection.setAutoCommit(false); PreparedStatement statement1 = connection.prepareStatement(sql1); PreparedStatement statement2 = connection.prepareStatement(sql2); statement1.setInt(1,100); statement1.setInt(2,1); statement1.executeUpdate(); //出现异常 //int i = 1/0; statement2.setInt(1,100); statement2.setInt(2,2); statement2.executeUpdate(); //转账入账的流程结束,提交事务,事务流程结束 connection.commit(); } catch (SQLException throwables) { try { //如果出现异常就对事务进行回滚,结束事务 connection.rollback(); } catch (SQLException e) { e.printStackTrace(); } } } }
import java.io.*; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Properties; public class JDBCUtils { private static String url; private static String username; private static String password; private static String driver; static { Properties pro = new Properties(); try { pro.load(JDBCUtils.class.getResourceAsStream("jdbc.properties")); url = pro.getProperty("jdbc.url"); username = pro.getProperty("jdbc.username"); password = pro.getProperty("jdbc.password"); driver = pro.getProperty("jdbc.driver"); Class.forName(driver); }catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection(){ try { return DriverManager.getConnection(url,username,password); } catch (SQLException throwables) { throwables.printStackTrace(); return null; } } }
jdbc.driver = com.mysql.cj.jdbc.Driver jdbc.url = jdbc:mysql://localhost:3306/java2106 jdbc.username = root jdbc.password = 123456
这篇关于JDBC知识点整理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-02在 Objective-C 中strong 和 retain有什么区别-icode9专业技术文章分享
- 2024-11-02NSString 中的 hasPrefix 有什么作用-icode9专业技术文章分享
- 2024-11-02在 C 和 Objective-C 中inline的用法是什么-icode9专业技术文章分享
- 2024-11-02文件掩码什么意思?-icode9专业技术文章分享
- 2024-11-02在 Git 提交之前运行 composer cs-fix 命令怎么实现-icode9专业技术文章分享
- 2024-11-02为 Composer 的 cs-fix 命令指定一个目录怎么实现-icode9专业技术文章分享
- 2024-11-02微信公众号开发中怎么获取用户的 unionid-icode9专业技术文章分享
- 2024-11-01lip-sync公司指南:一文读懂主要玩家和技术
- 2024-11-01Anthropic的新RAG方法——提升大型语言模型在特定领域的表现
- 2024-11-01UniApp 中组件的生命周期是多少-icode9专业技术文章分享