HOME> 梅西世界杯队友> JDBC 常用类介绍

JDBC 常用类介绍

# 4.JDBC 常用类介绍 上一节我们快速入门了下 JDBC,并使用它做了一个小案例,现在对各个常用的类做进一步的说明: DriverManager:驱动管理对象 C...

# 4.JDBC 常用类介绍 上一节我们快速入门了下 JDBC,并使用它做了一个小案例,现在对各个常用的类做进一步的说明:

DriverManager:驱动管理对象 Connection:数据库连接对象 Statement、PreparedStatement:执行 sql 的对象 ResultSet:结果集对象,封装查询结果 ‍

‍严格来说,以上这些都是接口,位于 java.sql 包下;

javax.sql 是数据库扩展包,提供数据库额外的功能,如连接池

# DriverManager:驱动管理对象 DriverManager 主要用两个功能:

注册驱动 获取数据库连接对象

‍ # 功能 1:注册驱动 注册驱动,告诉程序该使用哪一个数据库驱动 jar。

DriverManager 是一个接口,在 API 文档中有这样一个方法:static void registerDriver(Driver driver),作用是注册与给定的驱动程序。调用这个方法,实际上才算告诉了应用程序我们要使用哪个数据库驱动类。

但我们写代码的时候,直接通过反射加载驱动类:Class.forName("com.mysql.cj.jdbc.Driver"),好像也没有执行上面的注册方法?

这是因为驱动类有个 static 静态代码块,其中就会执行 registerDriver 方法,注册驱动,因此我们只要一加载这个类,就会自动注册。

说起一加载类就执行的代码,读者们想到了什么?static (opens new window) 代码块。通过查看 MySQL 驱动类,com.mysql.cj.jdbc.Driver 源码,可以看到有 static 代码块,会执行 register 方法:

static {

try {

java.sql.DriverManager.registerDriver(new Driver());

} catch (SQLException E) {

throw new RuntimeException("Can't register driver!");

}

}

1234567注意点 1:读者可以直接在 IDEA 里查看 jar 包中的源码

注意点 2:mysql5 之后的驱动 jar 包可以省略注册驱动的步骤 Class.forName(.....),因为会自动注册驱动,所以可以如下省略注册的代码:

// MySQL5驱动类注册方法

Class.forName("com.mysql.jdbc.Driver");

// MySQL8驱动类注册方法

Class.forName("com.mysql.cj.jdbc.Driver");

12345自动注册的原理:寻找 jar 包的 META-INF/services/java.sql.Driver 文件,并读取里面配置的类然后加载。所以如果读者后续更换其他数据库驱动类后,想要注册但不知道驱动类的全类名,可以通过这个方法找到。

注意,MySQL 驱动 5.1.6 版本之前的 jar 包中,没有 META-INF/services 目录,因此如果用的是早期的 JDBC 驱动,还是得用 Class.forName(“com.mysql.jdbc.Driver”) ‍

# 功能 2: 获取数据库连接对象 DriverManager 还有一个重要的方法,获取 Connection 对象:static Connection getConnection(String url, String user, String password)

参数说明:

url:指定连接的路径。注意,不同数据库的 URL 语法可能不一样。以 MySQL 为例:

语法:jdbc:mysql://ip地址(或域名):端口号/数据库名称 例子:jdbc:mysql://localhost:3306/db3 如果连接的是本机 mysql 服务器,并且 mysql 服务默认端口是 3306,则 url 可以简写为:jdbc:mysql:///数据库名称 user:用户名

password:密码

# Connection:数据库连接对象 功能:

获取执行 sql 的对象

Statement createStatement() PreparedStatement prepareStatement(String sql) 管理事务:

开启事务:void setAutoCommit(boolean autoCommit):调用该方法设置参数为 false,即开启事务 提交事务:void commit() 回滚事务:void rollback() 后续我们会介绍事务。

# Statement:执行 sql 的对象 查询文档,相关说明是:用于执行静态 SQL 语句并返回其生成的结果的对象(参数是给定值的)

PreparedStatement 对象则是执行预编译的 SQL 语句对象(参数是后续设置的)

执行 sql 相关方法:

boolean execute(String sql):可以执行任意的 sql (了解即可,较少使用),返回值是 Boolean 类型,有结果集则是 true,没有则是 false int executeUpdate(String sql):执行 DML 语句(例如 insert、update、delete)、DDL 语句(例如 create,alter、drop)。不能执行查询语句

返回值:影响的行数,可以通过这个影响的行数判断 DML 语句是否执行成功 。返回值 > 0 的则执行成功,反之,则失败。执行 DDL 语句则返回 0。 ResultSet executeQuery(String sql):执行 DQL(select)语句,返回 ResultSet 对象 之前我们仅仅使用了 executeQuery,后续我们介绍 executeUpdate 方法。

# PreparedStatement 对象:防止 SQL 注入 PreparedStatement 继承了 Statement 接口。这个类能解决 SQL 注入问题

执行的是预编译的 SQL,SQL 中参数使用 ? 作为占位符

使用步骤:

定义 sql。注意:sql 的参数使用?作为占位符。如:

string sql = select * from user where username = ? and password = ?;

1 获取执行 sql 语句的对象 PreparedStatement

pstm = Connection.prepareStatement(String sql)

1 给占位符 ?赋值,用方法: setXXX(参数 1, 参数 2),例如 setDouble() ,setString() 等一系列方法

参数 1:?的位置编号 从 1 开始 参数 2:?的值 举例:setString(1, "PeterJXL") 执行 sql,接受返回结果,不需要传递 sql 语句

# ResultSet:结果集对象,封装查询结果 ResultSet:返回结果集对象(可以看作是一个数据库表)后,默认会有个游标(或者叫指针),游标的初始位置位于第一行之前;

第一次调用 next() 方法将会把第一行设置为当前行。

第二次调用 next() 方法游标移动到第二行,以此类推。

常用方法

boolean next() : 游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回 false,如果不是则返回 true。

getXXX(参数): 获取某一列的数据

XXX 代表数据类型 如:int getInt(),String getString(),double getDouble() 等等

参数:

如果是 int 类型:代表列的编号, 从 1 开始 如:getString(1) 如果是 String 类型:代表列名称。 如: getDouble("balance") 使用步骤总结:

使用 next() 方法使游标向下移动一行 通过 next() 方法的返回值判断是否还有数据,如果有则返回 true,如果没有则返回 false(可以理解为游标到了最后一行了,再往下就没数据了) 通过 getXXX(参数) 方法获取某一列的数据

如果 ResultSet 的游标已经到了最后一行,再调用一次 next(),会抛出异常: java.sql.SQLException: After end of result set

at com.mysql.jdbc.SQLError.createsQLException(SQLError.java: 959)

at com.mysql.jdbc.SOLError.createSQLException(SOLError.java: 898)

com.mysql.jdbc.SQLError.createSQLException(SOLError.java: 887)

com.mysql.jdbc.SoLError.createSQLException(SOLError.java: 862)

com.mysql.jdbc.ResultsetImpl.checkRowPos(ResultSetImpl.java: 790)

com.mysql.jdbc.ResultSetImpl.getInt(ResultSetImpl.iava: 2469)

.....

12345678‍

所以我们遍历 ResultSet 时通常是使用循环,每次判断是否到达了最后一行:

while(rs.next()){ //循环判断游标是否是最后一行末尾(判断是否有数据)

//获取数据并处理

int id = rs.getInt(1);

// .....省略其他代码

}

12345


结婚回礼一般回什么好 回礼给宾客比较实际的东西 轻略的意思,轻略是什么意思,轻略的解释