导读:
本篇是JAVA基础系列的第21篇,今天我们梳理JDBC(java连接数据库)的相关知识点。JDBC 指 Java 数据库连接,是一种标准Java应用编程接口( JAVA API),用来连接 Java 编程语言和广泛的数据库。
1.JDBC概述
概念:Java DataBase Connectivity Java 数据库连接, Java语言操作数据库 JDBC 规范定义接口 ,具体的实现由各大数据库厂商来实现。JDBC是 Java 访问数据库的标准规范,真正怎么操作数据库还需要具体的实现类,也就是数据库驱动。每个数据库厂商根据自家数据库的通信格式编写好自己数据库的驱动。所以我们只需要会调用 JDBC 接口中的方法即可,数据库驱动由数据库厂商提供。
使用 JDBC 的好处:
-
程序员如果要开发访问数据库的程序,只需要会调用JDBC接口中的方法即可,不用关注类是如何实现的
-
使用同一套 Java 代码,进行少量的修改就可以访问其他 JDBC 支持的数据库
2.使用 JDBC 开发使用到的包
会使用的包名 | 说明 |
---|---|
java.sql | 所有与JDBC访问数据库相关的接口和类 |
javax.sql | 数据库拓展包,提供数据库额外的功能。例如:连接池 |
数据库驱动包 | 由各大数据库厂商提供,需要额外下载,是对JDBC接口实现的类 |
3.JDBC 的核心 API
JDBC核心类库包含在java.sql包中。在操作JDBC时除异常类之外,最主要的是一个类和4个接口。
类:
-
DriverManager:负责管理JDBC驱动程序。使用JDBC驱动程序之前,必须先将驱动程序加载并注册后才可以使用,同时提供方法来建立与数据库的连接
-
SQLException:有关数据库操作的异常
接口:
-
Connection:此接口具有连接数据库的所有方法。该连接对象表示通信上下文,即,所有与数据库的通信仅通过这个连接对象进行。
-
Statement: 使用创建于这个接口的对象将 SQL 语句提交到数据库。除了执行存储过程以外,一些派生的接口也接受参数
-
PreparedStatement:表示预编译的 SQL 语句的对象。是Statement接口的子接口。
-
ResultSet :表示数据库结果集的数据表,通常通过执行查询数据库的语句生成
4.DriverManager类
DriverManager类是JDBC API提供的驱动管理类,用于管理数据库厂商提供的驱动类。
DriverManager类的作用:
-
管理和注册驱动(数据库厂商提供)
-
创建数据库的连接
Driver类由数据库厂家提供,作为java开发人员,只需要使用Driver接口就可以了。在编程中要连接数据库,必须先装载特定厂商的数据库驱动程序,不同的数据库有不同的装载方法。
-
装载MySql驱动:
Class.forName("com.mysql.jdbc.Driver");
-
装载Oracle驱动:
Class.forName("oracle.jdbc.driver.OracleDriver");
5.Connection接口
Connection 接口是JDBC API提供的连接接口,具体的实现类由数据库的厂商实现,代表一个连接对象。
Connection 接口与特定数据库的连接(会话),在连接上下文中执行sql语句并返回结果。我们可以通过驱动管理类创建连接对象。
DriverManager.getConnection("数据库连接URL", "数据库用户名", "数据库密码")方法建立在JDBC URL中定义的数据库Connection连接上
-
连接MySql数据库:
Connection conn = DriverManager.getConnection("jdbc:mysql://host:port/database", "user", "password");
-
连接Oracle数据库:
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@host:port:database", "user", "password");
-
连接SqlServer数据库
Connection conn = DriverManager.getConnection("jdbc:microsoft:sqlserver://host:port; DatabaseName=database", "user", "password");
常用方法:
-
createStatement():创建向数据库发送sql的statement对象。
-
prepareStatement(sql) :创建向数据库发送预编译sql的PrepareSatement对象。
-
prepareCall(sql):创建执行存储过程的callableStatement对象。
-
setAutoCommit(boolean autoCommit):设置事务是否自动提交。
-
commit() :在链接上提交事务。
-
rollback() :在此链接上回滚事务。
6.Statement接口
代表一条语句对象,用于发送 SQL 语句给服务器,用于执行静态 SQL 语句并返回它所生成结果的对 象
三种Statement类:
-
Statement:由createStatement创建,用于发送简单的SQL语句。
-
PreparedStatement :继承自Statement接口,由preparedStatement创建,用于发送含有一个或多个参数的SQL语句。PreparedStatement对象比Statement对象的效率更高,并且可以防止SQL注入,所以我们一般都使用PreparedStatement。
-
CallableStatement:继承自PreparedStatement接口,由方法prepareCall创建,用于调用存储过程。
常用Statement方法:
-
execute(String sql):运行语句,返回是否有结果集
-
executeQuery(String sql):运行select语句,返回ResultSet结果集。
-
executeUpdate(String sql):运行insert/update/delete操作,返回更新的行数。
-
addBatch(String sql):把多条sql语句放到一个批处理中。
-
executeBatch():向数据库发送一批sql语句执行。
Statement接口在执行SQL语句时存在SQL注入风险。
SQL 注入问题
当我们登录时输入以下密码
请输入用户名:
admin
请输入密码:a' or '1'='1
select * from user where name='newboy' and password='a' or '1'='1'
登录成功,欢迎您:admin
7.PreparedStatement 接口
PreparedStatement 是 Statement 接口的子接口,继承于父接口中所有的方法。它是一个预编译的 SQL 语句
PreparedStatement 接口的优势
-
因为有预先编译的功能,提高 SQL 的执行效率。
-
可以有效的防止 SQL 注入的问题,安全性更高。
-
需要传参时结构更加清晰简洁,提高了程序的可读性,更利于维护。
8.ResultSet接口
ResultSet 接口是用来封装数据库查询的结果集
常用的方法有:
-
getString(int index)、getString(String columnName):获得在数据库里是varchar、char等类型的数据对象。
-
getFloat(int index)、getFloat(String columnName):获得在数据库里是Float类型的数据对象。
-
getDate(int index)、getDate(String columnName):获得在数据库里是Date类型的数据。
-
getBoolean(int index)、getBoolean(String columnName):获得在数据库里是Boolean类型的数据。
-
getObject(int index)、getObject(String columnName):获取在数据库里任意类型的数据。
ResultSet还提供了对结果集进行滚动的方法:
-
next():移动到下一行
-
Previous():移动到前一行
-
absolute(int row):移动到指定行
-
beforeFirst():移动resultSet的最前面。
-
afterLast() :移动到resultSet的最后面。
9.使用JDBC的步骤(PreparedStatement)
-
导入数据库厂商提供的数据库驱动jar包
-
通过Class.forName(驱动类完整路径)加载和注册驱动类
-
通过DriverManager类创建Connection连接对象
-
编写SQL语句,需要传参使用问号占位
-
通过连接对象创建PreparedStatement对象并预处理SQL语句
-
通过PreparedStatement对象处理问号,将其换为正确的参数值
-
执行SQL语句返回结果或者结果集(ResultSet)
-
处理结果或者结果集(依次关闭对象及连接:ResultSet → Statement → Connection)
-
关闭连接释放资源
10.示例代码
使用Statement接口实现方式(如果输入参数会有SQL注入风险)
public static void main(String[] args) throws SQLException { //1) 得到连接对象 Class.forName("com.mysql.jdbc.Driver"); Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/school","root","root"); //2) 得到语句对象 Statement statement = connection.createStatement(); //3) 执行 SQL 语句得到结果集 ResultSet 对象 ResultSet rs = statement.executeQuery("select * from student"); //4) 循环遍历取出每一条记录 while(rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); boolean gender = rs.getBoolean("gender"); Date birthday = rs.getDate("birthday"); //5) 输出的控制台上 System.out.println("编号:" + id + ", 姓名:" + name + ", 性别:" + gender + ", 生日:" +birthday); } //6) 释放资源 rs.close(); statement.close(); connection.close(); }
使用PreparedStatement接口实现方式
private static void login(String name, String password) throws SQLException { Class.forName("com.mysql.jdbc.Driver"); Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/school","root","root"); //写成登录 SQL 语句,没有单引号 String sql = "select * from user where name=? and password=?"; //得到语句对象 PreparedStatement ps = connection.prepareStatement(sql); //设置参数 ps.setString(1, name); ps.setString(2,password); ResultSet resultSet = ps.executeQuery(); if (resultSet.next()) { System.out.println("登录成功:" + name); } else { System.out.println("登录失败"); } //释放资源 resultSet.close(); ps.close(); connection.close(); }