JDBC,即 Java Database Connectivity,即 Java 数据库连接。是一种用于执行 SQL 语句的 Java API,它是 Java中的数据库连接规范。这个 API 为 Java 开发人员操作数据库提供了一个标准,可以为多种关系数据库提供统一访问。
API:Application Programming Interface(应用程序接口)
① Java 语言访问数据库操作完全面向抽象接口编程
② 开发数据库应用不用限定在特定数据库厂商的 API
③ 程序的可移植性大大增强,这和 Java 的特性是一样的,所以这正是 Java 语言拥有 JDBC 编程的原因。
1. 去 maven 仓库直接搜索 mysql,选择如下分组。
2. 找到一个与我们数据库的大版本号匹配的一个依赖版本。
3. 复制到 maven 项目中的 " pom.xml " 文件中。
4. 点击右侧的 " Maven ",并刷新。
5. 根据引入的依赖名字,在 IDEA 中搜索,如果找到的目录下如下,即可正常使用 JDBC 编程了。
DataSource 是一个接口。不能直接实例化,必须通过 它的实现类 MysqlDataSource 来实例化对象,而这个对象就相当于描述了数据库服务器在哪。
第一条语句:向上转型
后三条语句:向下转型
DataSource dataSource = new MysqlDataSource(); //向上转型
//设置数据库所在的地址
((MysqlDataSource) dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false");
//设置登录数据库的用户名
((MysqlDataSource) dataSource).setUser("root");
//设置登录数据库的密码
((MysqlDataSource) dataSource).setPassword("12345678");
//向下转型
解析上面的代码。
(1) setURL 方法中的 URL 是什么?
URL:Uniform Resource Locator 【统一资源定位符】
URL 是网络服务程序上用于指定信息位置的表示方法,简单地说,就是网址。
root 是 MySQL 管理员默认自带的管理员用户。
(3) setPassword 方法中,填的就是我们安装 MySQL 时设置的密码。
Connection connection = dataSource.getConnection();
选择 Connection 接口时,注意选择的是 java,.sql 下的包。
同时记得在方法中抛出异常。
为什么会需要我们抛出异常呢?抛出异常就证明,在后面写的代码中,程序非常有可能会发生异常,也许是受查异常,也许是非受查异常。举个例子,当你想与服务器建立连接的时候,你给的 URL 地址出错了,这就会发生异常,再举个列子,如果你的 URL 给对了,但密码又给错了,这是不是也无法让代码与服务器建立连接呢?
我们举一个插入数据表的一个例子,注意写法。
// 此处光是一个 String 类型的 SQL 还不行,需要把这个 String 包装成一个 "语句对象"
String sql = " insert into student values( 1, 'Jack' ) " ;
PreparedStatement statement = connection.prepareStatement(sql);
上面的操作旨在与将一个字符串风格的 SQL 语句转换成一个 JDBC 中的对象,后面我们需要通过 statement 执行其他操作。
//如果是 insert,update,delete 都是用 executeUpdate 方法
//如果是 select,使用 executeQuery 方法
int ret = statement.executeUpdate();
System.out.println(ret);
上面接收的返回值就表示当前这个操作,影响到了几行 ( 即哪一行被操作成功了,哪一行被操作失败了 ),对应 cmd 窗口的下列输出。本质上就是当一个 SQL 语句执行完之后,服务器给你的提示。
// 先创建的,后释放;后创建的,先释放
// 先打开冰箱,后打开抽屉;而先关闭抽屉,后关闭冰箱
statement.close();
connection.close();
这和 C语言中的 free 方法很像,只不过 C语言中 free方法需要搭配 malloc 方法使用。本质上就是说,把之前在内存中执行的资源释放掉,那么新空出来的内存供给其他使用。
而 Java 中自带垃圾回收机制,JVM 可以自动释放内存。但在这里连接的时候,情况又有不同,JVM 会从系统中申请到一些硬件资源,所以当 SQL 执行完后,还是得记得释放。
JDBC 编程中常用的一些接口、 类:
1. DataSource 接口 / MysqlDataSource 类
用来描述数据源和描述数据库的地址,( 端口,数据库名,用户名,密码)
我们常用 getConnection 方法
2. Connection 接口
表示数据库连接
我们常用 prepareStatement 方法
3. PreparedStatement 接口
通过这个对象来描述要执行的SQL,还可以对 SQL 进行动态拼接。
我们常用 executeUpdate/executeQuery 方法
注意:
不管 JDBC 编程使用了什么类、什么接口,也不管代码是怎么编程的,但有一点我们需要明确:核心永远在 SQL 语句上。 因为 JDBC 代码始终是固定写法,不管底层是怎么实现的,或许我们不理解它的原理,多写几次代码,依然能记住。但 SQL 语句就不一样了,本质上,就是 SQL 对数据库起直接作用。
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Test1 {
public static void main(String[] args) throws SQLException {
//1. 创建好数据源
DataSource dataSource = new MysqlDataSource();
//设置数据库所在的地址
((MysqlDataSource) dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test6?characterEncoding=utf8&useSSL=false");
//设置登录数据库的用户名
((MysqlDataSource) dataSource).setUser("root");
//设置登录数据库的密码
((MysqlDataSource) dataSource).setPassword("12345678");
//2. 让代码和数据库服务器建立连接
Connection connection = dataSource.getConnection();
//3. 操作数据库
String sql = " insert into student values( 1, 'Jack' ) " ;
PreparedStatement statement = connection.prepareStatement(sql);
//4. 执行 SQL
int ret = statement.executeUpdate();
System.out.println(ret);
//5. sql 执行完毕,需要释放资源
statement.close();
connection.close();
}
}
输出结果为:1 (表示插入一行成功)
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
/**
* 添加学生的学号和姓名
*/
public class Test2 {
public static void main(String[] args) throws SQLException {
//1. 创建好数据源
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource) dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test6?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("1234567");
//2. 让代码和数据库服务器建立连接
Connection connection = dataSource.getConnection();
//2.1 让用户通过控制台输入一下待插入的数据
Scanner scanner = new Scanner(System.in);
System.out.println("输入学号: ");
int id = scanner.nextInt();
System.out.println("输入姓名: ");
String name = scanner.next();
//3. 操作数据库
String sql = " insert into student values(?,?) " ;
PreparedStatement statement = connection.prepareStatement(sql);
//3.1 进行替换操作
statement.setInt(1,id);
statement.setString(2,name);
System.out.println("statement: " + statement);
//4. 执行 SQL
int ret = statement.executeUpdate();
System.out.println(ret);
//5. sql 执行完毕,需要释放资源
statement.close();
connection.close();
}
}
我们可以通过控制台输入来执行输入对应的字段值。
输出结果:下面的红色框框,我们可以验证是否正确插入。
看看下列四行代码,是否有些疑惑?
String sql = " insert into student values(?,?) " ;
statement.setInt(1,id);
statement.setString(2,name);
System.out.println("statement: " + statement);
针对这四行代码,解释如下图:
" ? " 表示占位符,相当于告诉 Java,这两个待插入的值还未确定,而第一个问号索引是从 1 开始的,第二个索引为2,依次往后… 其中,set 方法表示替换
而我们打印出来 statement 就是为了检查替换是否正确 !
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Scanner;
/**
* 根据学生 id 进行删除操作
*/
public class Test3 {
public static void main(String[] args) throws SQLException {
//1. 创建好数据源
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource) dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test6?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("1234567");
//2. 让代码和数据库建立连接
Connection connection = dataSource.getConnection();
//3. 输入需要删除的学号
Scanner scanner = new Scanner(System.in);
System.out.println("输入学号:");
int id = scanner.nextInt();
//4. 操作数据库
String sql = "delete from student where id = ?" ;
PreparedStatement statement = connection.prepareStatement(sql);
statement.setInt(1,id);
System.out.println("statement: " + statement);
//5. 执行 SQL
int ret = statement.executeUpdate();
System.out.println("ret: " + ret);
//6. SQL 执行完毕,需要释放资源
statement.close();
connection.close();
}
}
输出结果:
现在再看 测试3 的代码时,就很简单了,因为套路是一样的,JDBC 编程实现 增、删、改 的基本流程都是固定的。针对 SQL语句的 update 操作,我就不演示了,思想和上面都是相同的。
在测试4 中,我们演示了查询操作,查询操作比较于增删改,多了一个步骤:遍历结果集,即把结果中的数据获取到。
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Test4 {
public static void main(String[] args) throws SQLException {
//1. 创建数据源
DataSource dataSource = new MysqlDataSource();
((MysqlDataSource) dataSource).setURL("jdbc:mysql://127.0.0.1:3306/test6?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("1234567");
//2. 建立连接
Connection connection = dataSource.getConnection();
//3. 操作数据库
String sql = " select * from student";
PreparedStatement statement = connection.prepareStatement(sql);
//4. 执行 SQL
// 查询操作与 增删改 不同,它始终是一个临时表,我们将临时表用 resultSet 接收
ResultSet resultSet = statement.executeQuery();
//5. 遍历 resultSet,固定写法
//先获取到某一行,再获取到这一行的所有列
//next 方法表示获取到一行数据,同时把光标往后移动一行
//如果遍历到表的末尾,此处的 next 直接返回 false
while (resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
System.out.println( "id= " +id + ", name= " +name);
}
//6. 释放资源
resultSet.close();
statement.close();
connection.close();
}
}
输出结果:
对应 cmd 控制台:
分析 while 循环,这是一种固定写法。
针对结果集,我们依次获取到表中的每一行,再通过这一行来获取此行对应的列。
第一次执行 resultSet.next(),表示获取到了第一行( id = 1 )
第二次执行 resultSet.next(),表示获取到了第二行( id = 2 )
第三次执行 resultSet.next(),由于表到达了末尾,next 方法返回了 false,循环结束。
while (resultSet.next()){
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
System.out.println( "id= " +id + ", name= " +name);
}