一、JDBC概述
(一)什么是JDBC
JDBC全称Java DataBase Connectivity。Java数据库连接, 是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。
JDBC是接口,而JDBC驱动才是接口的实现,没有驱动无法完成数据库连接。每个数据库厂商都有自己的驱动,用来连接自己公司的数据库。
- JDBC核心类(接口)介绍
JDBC中的核心类(接口)有:DriverManager、Connection、Statement,和ResultSet(java.sql)。
1、DriverManager
DriverManger(驱动管理器)的作用有两个:
注册驱动:这可以让JDBC知道要使用的是哪个驱动。
获取Connection:如果可以获取到Connection,那么说明已经与数据库连接上了。
2、Connection
Connection对象表示连接,与数据库的通讯都是通过这个对象展开的。
Connection最为重要的一个方法就是用来获取Statement对象。
3、Statement
Statement是用来向数据库发送SQL语句的,这样数据库就会执行发送过来的SQL语句。
4、ResultSet
ResultSet对象表示查询结果集,只有在执行查询操作后才会有结果集的产生。结果集是一个二维的表格,有行有列。操作结果集要学习移动ResultSet内部的“行光标”,以及获取当前行上的每一列上的数据。
第一个JDBC程序
1.数据准备
2.开发步骤:
- 下载驱动jar包
- 创建项目导入驱动
- 程序编写: (1) 加载驱动 (2) 获取连接 (3) 获得执行SQL语句的对象 (4) 执行SQL (5) 处理结果集 (6)释放资源 (7) 完整案例
(1) 加载驱动 作用:告诉JVM使用哪个驱动类
语法
Class.forName("com.mysql.cj.jdbc.Driver");
8.0以前版本
Class.forName("com.mysql.jdbc.Driver");
(2) 获取连接
作用:获取到连接数据库的对象。
语法
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai","root","mysql");
8.0以前版本
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1?useUnicode=true&characterEncoding=utf8","root","mysql");
(3) 获得执行SQL语句的对象
获取Statement对象,用来向数据库发送SQL语句。
通过Connection对象的createStatement()方法来获取。
语法
Statement st = conn.createStatement();
(4) 执行SQL
通过Statement对象把SQL语句发送给数据库执行。
executeUpdate(SQL语句)用来执行增、删、改语句。
executeQuery(SQL语句)用来执行查询语句。
语法
String sql = "select * from student";
ResultSet rs = st.executeQuery(sql);
(5) 处理结果集
ResultSet就是一张二维的表格,它内部有一个“行光标”,光标默认的位置在“第一行上方”,我们可以调用rs对象的next()方法把“行光标”向下移动一行,当第一次调用next()方法时,“行光标”就到了第一行记录的位置,这时就可以使用ResultSet提供的getXXX(int col)或getXXX(“列名”)方法来获取指定列的数据了。
next()方法有两层含义:第一,判断行光标是否可以移动。第二,移动行光标。
getXXX()方法有两种写法:getXXX(int col)或getXXX(“列名”)
rs.getInt(1);获取第一列数据
rs.getInt(“id”)获取id列数据
在ResultSet类中提供了一系列的getXXX()方法,比较常用的方法有:
Object getObject(int col或列名)
String getString(int col或列名)
int getInt(int col或列名)
double getDouble(int col或列名)
语法
while(rs.next()){
System.out.println(rs.getInt("id")+"\t"+rs.getString("name")+"\t"+rs.getInt("age")+"\t"+rs.getDate("birthday"));
}
(6)释放资源
所谓释放资源是指开启的连接Connection、执行SQL语句的对象Statement、结果集ResultSet在使用完成后,必须关闭。
语法
rs.close();
st.close()
conn.close();
(7) 完整案例
package com.offcn.demo01;
import java.sql.*;
/*
查询所有内容展示到控制台
*/
public class JDBCTest01 {
public static void main(String[] args) {
try {
// 1、加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2、获取连接 3个参数
//url: 连接mysql ip 端口 数据库名 参数:前两个参数编码解码 useSSL:安全验证 serverTimezone时区
//user: 用户
//password: 密码
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1?useUnicode=true&" +
"characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai","root","root");
// 3、获得执行sql语句的对象 Statement
Statement st = conn.createStatement();
// 4、执行sql语句
//2个方法 executeQuery(sql) 查询 executeUpdate(sql) 增删改
String sql = "select * from student";
ResultSet rs = st.executeQuery(sql);
// 5、处理结果集 next() 判断是否可以向下移动光标 移动光标到下一行
while(rs.next()){
//getXXX(列名) getXXX(第几列 1,2,3,4)
System.out.println(rs.getInt("id") + "\t" + rs.getString("name") + "\t" +
rs.getInt("age") + "\t" + rs.getDate("birthday"));
}
// 6、释放资源
rs.close();
st.close();
conn.close();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
4.规范代码
package com.offcn.demo01;
import java.sql.*;
/*
查询所有内容展示到控制台
*/
public class JDBCTest01 {
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
// 1、加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2、获取连接 3个参数
//url: 连接mysql ip 端口 数据库名 参数:前两个参数编码解码 useSSL:安全验证 serverTimezone时区
//user: 用户
//password: 密码
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1?useUnicode=true&" +
"characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai","root","root");
// 3、获得执行sql语句的对象 Statement
st = conn.createStatement();
// 4、执行sql语句
//2个方法 executeQuery(sql) 查询 executeUpdate(sql) 增删改
String sql = "select * from student";
rs = st.executeQuery(sql);
// 5、处理结果集 next() 判断是否可以向下移动光标 移动光标到下一行
while(rs.next()){
//getXXX(列名) getXXX(第几列 1,2,3,4)
System.out.println(rs.getInt(1) + "\t" + rs.getString("name") + "\t" +
rs.getInt("age") + "\t" + rs.getDate("birthday"));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally{
// 6、释放资源
if(rs != null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(st != null){
try {
st.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
三、使用JDBC完成CRUD操作
(一)准备数据
使用第一个案例中的student表即可。
(二)添加数据
1、需求
从键盘录入数据,添加到student表中。
2、步骤
1、从控制台获取数据
2、加载驱动
3、获取连接Connection
4、获取执行SQL的对象Statement
5、拼接SQL语句
6、执行SQL
7、释放资源
- 示例代码
package com.offcn.demo02;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
//从键盘录入数据,添加到student表中。
public class JDBCTest02 {
public static void main(String[] args) {
// 键盘录入 获取录入数据
Scanner sc = new Scanner(System.in);
// 提示
System.out.println("请输入您的姓名:");
String name = sc.nextLine();
System.out.println("请输入您的年龄:");
String age = sc.nextLine();
System.out.println("请输入您的生日:");
String birthday = sc.nextLine();
Connection conn = null;
Statement st = null;
try { //ctrl+alt+t
// 1、注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 2、获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1?useUnicode=true&" +
"characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai", "root", "root");
// 3、获取执行sql的对象
st = conn.createStatement();
// 4、拼接sql insert into student values(null,'张三丰',30,'1991-01-05');
String sql = "insert into student values(null,'" + name + "'," + age + ",'" + birthday + "')";
// 5、执行sql
int i = st.executeUpdate(sql);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
// 6、释放资源
if(st != null){
try {
st.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
(三)更新数据
1、需求
根据键盘输入的内容,更新student表中的指定数据
- 步骤
1、从控制台获取数据
2、加载驱动
3、获取连接Connection
4、获取执行SQL的对象Statement
5、拼接SQL语句
6、执行SQL
7、释放资源
3、示例代码
package com.offcn.demo02;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
//根据键盘输入的内容,更新student表中的指定数据
public class JDBCTest03 {
public static void main(String[] args) {
// 1、从控制台获取数据
Scanner sc = new Scanner(System.in);
System.out.println("请输入要修改的id:");
String id = sc.nextLine();
System.out.println("请输入姓名:");
String name = sc.nextLine();
System.out.println("请输入年龄:");
String age = sc.nextLine();
System.out.println("请输入生日:");
String birthday = sc.nextLine();
Connection conn = null;
Statement st = null;
try {
// 2、加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 3、获取连接Connection
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1?useUnicode=true&" +
"characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai", "root", "root");
// 4、获取执行SQL的对象Statement
st = conn.createStatement();
// 5、拼接SQL语句 update student set name = '钱七',age = 25,birthday = '1996-05-06' where id = 5;
String sql = "update student set name = '" + name + "',age = " + age + ",birthday = '" + birthday +
"' where id = " + id;
// 6、执行SQL
st.executeUpdate(sql);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
// 7、释放资源
if(st != null){
try {
st.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
(四)删除数据
- 需求
根据输入的id删除student表中的指定数据。
- 步骤
1、从控制台获取数据
2、加载驱动
3、获取连接Connection
4、获取执行SQL的对象Statement
5、拼接SQL语句
6、执行SQL
7、释放资源
- 示例代码
package com.offcn.demo02;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
//根据id删除
public class JDBCTest04 {
public static void main(String[] args) {
// 1、从控制台获取数据
Scanner sc = new Scanner(System.in);
System.out.println("请输入要删除id:");
String id = sc.nextLine();
Connection conn = null;
Statement st = null;
try {
// 2、加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 3、获取连接Connection
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1?useUnicode=true&" +
"characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai", "root", "root");
// 4、获取执行SQL的对象Statement
st = conn.createStatement();
// 5、拼接SQL语句 delete from student where id = 5;
String sql = "delete from student where id = " + id;
// 6、执行SQL
st.executeUpdate(sql);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
// 7、释放资源
if(st != null){
try {
st.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
(五)查询全部
1、需求
查询student表中全部数据。
2、步骤
具体开发步骤与第一个jdbc程序相同。
3、示例代码
代码与第一个jdbc程序相同。
(六)根据id查询
1、需求
根据键盘输入的id查询指定数据。
2、步骤
1、从控制台获取数据
2、加载驱动
3、获取连接Connection
4、获取执行SQL的对象Statement
5、拼接SQL语句
6、执行SQL
7、处理结果集合
8、释放资源
3、示例代码
package com.offcn.demo02;
import java.sql.*;
import java.util.Scanner;
//根据id查询
public class JDBCTest05 {
public static void main(String[] args) {
// 1、从控制台获取数据
Scanner sc = new Scanner(System.in);
System.out.println("请输入id:");
String id = sc.nextLine();
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
// 2、加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 3、获取连接Connection
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb1?useUnicode=true&" +
"characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai","root","root");
// 4、获取执行SQL的对象Statement
st = conn.createStatement();
// 5、拼接SQL语句
String sql = "select * from student where id = " + id;
// 6、执行SQL
rs = st.executeQuery(sql);
// 7、处理结果集合
while(rs.next()){
System.out.println(rs.getInt("id") + "\t" + rs.getString("name") +
"\t" + rs.getInt("age") + "\t" + rs.getDate("birthday"));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
// 8、释放资源
if(rs != null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(st != null){
try {
st.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
- 根据name模糊查询
- 需求
根据键盘输入的name值进行模糊查询。
- 步骤
1、从控制台获取数据
2、加载驱动
3、获取连接Connection
4、获取执行SQL的对象Statement
5、拼接SQL语句
6、执行SQL
7、处理结果集合
8、释放资源
- 示例代码
- 封装JDBC工具类
通过上面的增、删、改、查操作我们发现,加载驱动、获取连接和释放资源都是重复操作。可以封装一个工具类,类中包括获取连接和释放资源的方法。
为了便于日后项目的修改和维护,数据库的连接信息可以存放在一个properties文件中。在工具类中读取信息。
src/db.properties
driverClass=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb1?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username=root
password=root
示例代码
package com.offcn.demo02;
import java.sql.*;
import java.util.ResourceBundle;
//工具类
public class JDBCUtil {
// 1、定义数据连接
private static String driverClass;
private static String url;
private static String username;
private static String password;
// 静态代码块
static {
try {
// 2、加载properties文件 取4个值
ResourceBundle rb = ResourceBundle.getBundle("db");//不需要写后缀
driverClass = rb.getString("driverClass");
url = rb.getString("url");
username = rb.getString("username");
password = rb.getString("password");
//3、静态代码块 加载驱动 只加载一次
Class.forName(driverClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
// 4、获取连接 返回值Connection 不要参数
public static Connection getConnection(){
Connection conn = null;
try {
conn = DriverManager.getConnection(url, username, password);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return conn;
}
// 5、释放资源 不需要返回值类型 需要参数 Connection Statement ResultSet
public static void close(Connection conn, Statement st, ResultSet rs){
if(rs != null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(st != null){
try {
st.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
// 释放资源 需要两参数 Connection Statement 方法重载
public static void close(Connection conn,Statement st){
close(conn,st,null);
}
}
package com.offcn.demo02;
import java.sql.*;
import java.util.Scanner;
//根据id查询
public class JDBCTest06 {
public static void main(String[] args) {
// 1、从控制台获取数据
Scanner sc = new Scanner(System.in);
System.out.println("请输入id:");
String id = sc.nextLine();
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
// 2、加载驱动
// 3、获取连接Connection
conn = JDBCUtil.getConnection();
// 4、获取执行SQL的对象Statement
st = conn.createStatement();
// 5、拼接SQL语句
String sql = "select * from student where id = " + id;
// 6、执行SQL
rs = st.executeQuery(sql);
// 7、处理结果集合
while(rs.next()){
System.out.println(rs.getInt("id") + "\t" + rs.getString("name") +
"\t" + rs.getInt("age") + "\t" + rs.getDate("birthday"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
// 8、释放资源
JDBCUtil.close(conn,st,rs);
}
}
}
四、JDBC事务
(一)概述
mysql默认是自动提交事务的,如果想同时执行多条SQL语句,而且要保证多条SQL同时成功,那么就需要手动的来提交事务。
Jdbc默认也是自动提交事务的,可以设置为手动提交。
为了让多个 SQL 语句作为一个事务执行:
调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务。
在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务
在出现异常时,调用 rollback(); 方法回滚事务。
(二)案例
- 需求
转账案例,账户1向账户2转账。要求事务控制,保证同时成功或同时失败。
- 数据准备
创建账户表,添加数据
create table account(
id int primary key, -- 账户id
money int -- 账户钱数
);
insert into account values(1,10000);
insert into account values(2,10000);
- 示例代码
- 不加入事务控制
package com.offcn;
import com.offcn.demo02.JDBCUtil;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
public class JDBCTest01 {
public static void main(String[] args) {
// 1、从控制台获取数据
Scanner sc = new Scanner(System.in);
System.out.println("请输入转出账户:");
String id1 = sc.nextLine();
System.out.println("请输入转入账户:");
String id2 = sc.nextLine();
System.out.println("请输入转账金额:");
String money = sc.nextLine();
Connection conn = null;
Statement st = null;
try {
// 2、加载驱动
// 3、获取连接Connection
conn = JDBCUtil.getConnection();
// 4、获取执行SQL的对象Statement
st = conn.createStatement();
// 5、拼接sql
// update account set money = money - 1000 where id = 1;
// update account set money = money + 1000 where id = 2;
String sql1 = "update account set money = money - " + money + " where id = " + id1;
String sql2 = "update account set money = money + " + money + " where id = " + id2;
// 6、执行sql
st.executeUpdate(sql1);
st.executeUpdate(sql2);
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
// 7、释放资源
JDBCUtil.close(conn,st);
}
}
}
- 事务控制
package com.offcn;
import com.offcn.demo02.JDBCUtil;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
public class JDBCTest01 {
public static void main(String[] args) {
// 1、从控制台获取数据
Scanner sc = new Scanner(System.in);
System.out.println("请输入转出账户:");
String id1 = sc.nextLine();
System.out.println("请输入转入账户:");
String id2 = sc.nextLine();
System.out.println("请输入转账金额:");
String money = sc.nextLine();
Connection conn = null;
Statement st = null;
try {
// 2、加载驱动
// 3、获取连接Connection
conn = JDBCUtil.getConnection();
//取消事务自动提交 更改为手动提交事务 false
conn.setAutoCommit(false);
// 4、获取执行SQL的对象Statement
st = conn.createStatement();
// 5、拼接sql
// update account set money = money - 1000 where id = 1;
// update account set money = money + 1000 where id = 2;
String sql1 = "update account set money = money - " + money + " where id = " + id1;
String sql2 = "update account set money = money + " + money + " where id = " + id2;
// 6、执行sql
st.executeUpdate(sql1);
int i = 5 / 0; //执行完sql1之后 出现异常 sql2没有执行
st.executeUpdate(sql2);
//事务提交 保证sql全部执行完毕
conn.commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
try {
//如果在有异常的情况下 ,才进行事务回滚
conn.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
} finally {
// 7、释放资源
JDBCUtil.close(conn,st);
}
}
}
作业
1、使用jdbc完成键盘输入的增删改查操作(jdbc工具类)