1.什么是JDBC
JDBC 规范定义接⼝,具体的实现由各⼤数据库⼚商来实现。
- 使⽤JDBC的好处:
- 程序员如果要开发访问数据库的程序,只需要会调⽤ JDBC 接⼝中的⽅法即可,不⽤关
注类是如何实现的。 - 使⽤同⼀套 Java 代码,进⾏少量的修改就可以访问其他 JDBC ⽀持的数据库。
- JDBC的核⼼API
- 加载和注册驱动
2.DriverManager类
- 管理和注册驱动
- 创建数据库的连接
- 类中的方法
- 使⽤JDBC连接数据库的四个参数
- 连接数据库的URL地址格式
jdbc:mysql://ip:port/database?serverTimezone=UTC
jdbc:mysql://localhost:3306/数据库?serverTimezone=GMT
jdbc:mysql:///数据库名
- 例:得到MySQL的数据库连接对象
/**
* 得到连接对象
*/
public class Demo2 {
public static void main(String[] args) throws SQLException {
String url = "jdbc:mysql://localhost:3306/day24";
// 1) 使⽤⽤户名、密码、URL 得到连接对象
Connection connection = DriverManager.getConnection(url, "root","rootroot");
// com.mysql.jdbc.JDBC4Connection@68de145
System.out.println(connection);
}
}
- 例:写一个mysql连接的工具类
public class JDBCutils {
private static String driver;
private static String url;
private static String username;
private static String password;
static {
Properties pro = new Properties();
try {
pro.load(JDBCutils.class.getResourceAsStream("JDBC.properties"));
driver = pro.getProperty("JDBC.Driver");
url = pro.getProperty("JDBC.url");
username = pro.getProperty("JDBC.username");
password = pro.getProperty("JDBC.password");
Class.forName(driver);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
try {
return DriverManager.getConnection(url,username,password);
} catch (SQLException throwables) {
throwables.printStackTrace();
}return null;
}
}
3.Connection接⼝
Connection 接⼝,具体的实现类由数据库的⼚商实现,代表⼀个连接对象。
- 方法
4.Statement接⼝
- JDBC访问数据库的步骤
- 注册和加载驱动(可以省略)
- 获取连接
- Connection 获取 Statement 对象
- 使⽤ Statement 对象执⾏ SQL 语句
- 返回结果集
- 释放资源
-
Statement作⽤
代表⼀条语句对象,⽤于发送 SQL 语句给服务器,⽤于执⾏静态 SQL 语句并返回它所⽣成结果的对象。 -
方法
boolean execute(sql); // DDL DML DQL
因为DML DQL有专门的执行方法, 所以execute通常用来执行DDL
int executeUpdate(sql); // 专门用来执行DML
ResultSet executeQuery(sql); // 专门用来执行DQL
- 释放资源
- 需要释放的对象:ResultSet 结果集,Statement 语句,Connection 连接
- 释放原则:先开的后关,后开的先关。ResultSet → Statement → Connection
- 放在哪个代码块中:finally 块
- DDL操作
conn = DriverManager.getConnection("jdbc:mysql:///day24", "root","root");
// 2. 通过连接对象得到语句对象
statement = conn.createStatement();
// 3. 通过语句对象发送 SQL 语句给服务器
// 4. 执⾏ SQL
statement.executeUpdate("create table student (id int PRIMARY key
auto_increment, " +"name varchar(20) not null, gender boolean, birthday date)");
// 5. 返回影响⾏数(DDL 没有返回值)
System.out.println("创建表成功");
- DML操作
Connection connection =
DriverManager.getConnection("jdbc:mysql:///test", "root", "root");
// 2) 创建Statement语句对象
Statement statement = connection.createStatement();
// 3) 执⾏SQL语句:executeUpdate(sql)
int count = 0;
// 4) 返回影响的⾏数
count += statement.executeUpdate("insert into student values(null,
'孙悟空', 1, '1993-03-24')");
count += statement.executeUpdate("insert into student values(null,
'⽩⻣精', 0, '1995-03-24')");
count += statement.executeUpdate("insert into student values(null,
'猪⼋戒', 1, '1903-03-24')");
count += statement.executeUpdate("insert into student values(null,
'嫦娥', 0, '1993-03-11')");
System.out.println("插⼊了" + count + "条记录");
- DQL操作
例:模拟登陆操作
package com.zzxx.jdbc01;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
public class Login {
public static void main(String[] args) throws SQLException {
Scanner sc = new Scanner(System.in);
System.out.println("请输入账号:");
String str1 = sc.nextLine();
System.out.println("请输入密码:");
String str2 = sc.nextLine();
Connection connection = JDBCutils.getConnection();
Statement sttt = connection.createStatement();
String sql ="select * from user1 where username='"+str1+"' and password='"+str2+"'";
//select * from user1 where username='xxx' and password='b' or 'a'='a'
System.out.println(sql);
ResultSet rs = sttt.executeQuery(sql);
if (rs.next()){
System.out.println("登陆成功");
}else {
System.out.println("账号/密码错误");
}
rs.close();
sttt.close();
connection.close();
}
}
5. PreparedStatement接⼝
PreparedStatement 是 Statement 接⼝的⼦接⼝,继承于⽗接⼝中所有的⽅法。它是⼀个预编译的 SQL 语句。
- Connection 创建 PreparedSatement 对象
- PreparedSatement 接⼝中的⽅法
- 使⽤ PreparedStatement 的步骤
- 编写 SQL 语句,未知内容使⽤?占位:“SELECT * FROM user WHERE name=? AND
password=?”; - 获得 PreparedStatement 对象
- 设置实际参数:setXxx (占位符的位置,真实的值)
- 执⾏参数化 SQL 语句
- 关闭资源
- 例:用户登陆(new)
package com.zzxx.jdbc01;
import java.sql.*;
import java.util.Scanner;
public class Login_new {
public static void main(String[] args) throws SQLException {
Scanner sc = new Scanner(System.in);
System.out.println("请输入账号:");
String str1 = sc.nextLine();
System.out.println("请输入密码:");
String str2 = sc.nextLine();
Connection connection = JDBCutils.getConnection();
String sql ="select * from user1 where username=? and password=?";
PreparedStatement sttt = connection.prepareStatement(sql);
sttt.setString(1,str1);
sttt.setString(2,str2);
ResultSet rs = sttt.executeQuery();
if (rs.next()){
System.out.println("登陆成功");
}else {
System.out.println("账号/密码错误");
}
rs.close();
sttt.close();
connection.close();
}
}
6.JDBC 事务的处理
使⽤ JDBC 来操作银⾏转账的事务。
- API 介绍
- 开发步骤
- 获取连接
- 开启事务
- 获取到 PreparedStatement
- 使⽤ PreparedStatement 执⾏两次更新操作
- 正常情况下提交事务
- 出现异常回滚事务
- 最后关闭资源
import com.bonnie.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Demo12Transaction {
// 没有异常,提交事务,出现异常回滚事务
public static void main(String[] args) {
// 1) 注册驱动
Connection connection = null; PreparedStatement ps = null;
try {
// 2) 获取连接
connection = JdbcUtils.getConnection();
// 3) 开启事务
connection.setAutoCommit(false);
// 4) 获取到PreparedStatement
// 从 jack 扣钱
ps = connection.prepareStatement("update account set balance =
balance - ? where name=?");
ps.setInt(1, 500);
ps.setString(2, "Jack");
ps.executeUpdate();
// 出现异常 System.out.println(100 / 0);
// 给 rose 加钱
ps = connection.prepareStatement("update account set balance =
balance + ? where name=?");
ps.setInt(1, 500);
ps.setString(2, "Rose");
ps.executeUpdate();
// 提交事务
connection.commit();
System.out.println("转账成功");
} catch (Exception e) {
e.printStackTrace();
try {
// 事务的回滚
connection.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
System.out.println("转账失败");
} finally {
// 7) 关闭资源
JdbcUtils.close(connection, ps);
}
}
}