概述
JDBC(java database connectivity)是java访问数据库的操作规范,实质上就是一个接口,具体的实现类(数据库驱动)由各个具体的数据库厂商实现。
JDBC核心API
接口或者类 | 作用 |
---|---|
DriverManager类 | 管理和注册数据库驱动(DriverManager.registerDriver)、获取数据库连接对象(DriverManager.getConnection) |
Connection接口 | 连接对象,可以创建Statement和PreparedStatement对象(con.createStatement) |
Statement接口 | SQL语句对象,将SQL语句发送给数据库服务器 |
PreparedStatement接口 | SQL语句对象,是Statement子接口,预编译对象,可以防止SQL注入 |
ResultSet接口 | 用于封装数据库查询的结果集,返回给客户端的java服务器。用next方法是游标。用getXxx方法获取该行不同字段结果 |
快速入门
导入驱动Jar包
新建文件夹lib,然后将Jar包放在该文件夹下,右键选择添加成library(Add as Library)
加载和注册驱动
Class.forName("com.mysql.jdbc.Driver");
为何可以这样注册驱动?我们知道将com.mysql.jdbc.Driver
加载进内存,会自动执行给类中静态代码块。
在该类的静态代码块中有注册驱动的代码
//Driver接口,所有数据库厂商必须实现的接口,表示这是一个驱动类
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
}
//该类加载进内存,会执行静态代码块
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}
注意:从JDBC3开始,目前已经普遍使用的版本,可以不用注册驱动直接使用。因为导入的驱动Jar包中META-INF文件中有对应的注册驱动配置
详解JDBC重要的API
DriverManager类
驱动管理,用于注册驱动(Class将驱动类加载,自动执行注册驱动)或者获取连接对象
获取连接对象
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "root");
连接数据库的 URL 地址格式
协议名:子协议://服务器或者IP地址:端口号/数据库名?参数=参数值
举例
jdbc:mysql://localhost:3306/db3?msg=hello
如果默认本机3306端口可以省略localhost:3306
jdbc:mysql:///db3
乱码处理
如果数据库出现乱码,可以指定参数?characterEncoding=utf8
jdbc:mysql://localhost:3306/数据库?characterEncoding=utf8
案例1使用用户名、密码、URL 得到连接对象
package com.itheima;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* 得到连接对象
*/
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", "root");
//com.mysql.jdbc.JDBC4Connection@68de145
System.out.println(connection);
} }
案例2使用属性文件和 url 得到连接对象
package com.itheima;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
public class Demo3 {
public static void main(String[] args) throws SQLException {
//url 连接字符串
String url = "jdbc:mysql://localhost:3306/day24";
//属性对象
Properties info = new Properties();
//把用户名和密码放在 info 对象中
info.setProperty("user","root");
info.setProperty("password","root");
Connection connection = DriverManager.getConnection(url, info);
//com.mysql.jdbc.JDBC4Connection@68de145
System.out.println(connection);
} }
Connection接口
Connection 接口,具体的实现类由数据库的厂商实现,代表一个连接对象。
接口中的方法
createStatement
创建一条SQL语句对象
Statement接口
代表语句对象,用于发送SQL语句给服务器,用于执行静态SQL语句并返回它生成结果的对象。
接口中的方法
executeUpdate 更新
executeQuery 查询
PreparedStatement接口
代表语句对象,用于发送SQL语句给服务器,这里的SQL语句参数要用?代替。用于执行动态SQL语句并返回它生成结果的对象。
可以防止SQL注入
本质上是和服务器协调固定了SQL语句的结构,防止了SQL注入。
接口中的方法
setXxx 设置?对应的参数
ResultSet接口
结果集对象,封装了查询结果
接口中的方法
boolean next()
游标向下移动一行,判断当前行是否是最后一行末尾(是否有数据),如果是,则返回false,如果不是则返回true
getXxx(参数) 获取数据
Xxx:代表数据类型 如: int getInt() , String getString()
参数
- int:代表列的编号,从1开始 如: getString(1)
- String:代表列名称。 如: getDouble(“balance”)
JDBC连接数据库步骤
- 导入数据库驱动jar包
- 加载注册驱动
- 获取连接对象
- 创建语句对象statement
- 定义sql,利用statement对象给数据库服务器发送执行
- 返回执行结果
- 关闭statement、connecttion、(resultSet)
抽取JDBC工具类 : JDBCUtils
主要是为了简化书写
步骤
- 定义jdbc.properties配置文件,包括
url、user、password、driver
属性 - 定义类,定义静态方法
- 定义property对象,读取配置文件属性
- 加载注册jdbc(静态代码块)
- 定义获取连接对象静态方法
- 定义close方法
代码
public class JDBCUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
/**
* 文件的读取,只需要读取一次即可拿到这些值。使用静态代码块
*/
static{
//读取资源文件,获取值。
try {
//1. 创建Properties集合类。
Properties pro = new Properties();
//获取src路径下的文件的方式--->ClassLoader 类加载器
ClassLoader classLoader = JDBCUtils.class.getClassLoader();
URL res = classLoader.getResource("jdbc.properties");
String path = res.getPath();
System.out.println(path);///D:/IdeaProjects/itcast/out/production/day04_jdbc/jdbc.properties
//2. 加载文件
// pro.load(new FileReader("D:\\IdeaProjects\\itcast\\day04_jdbc\\src\\jdbc.properties"));
pro.load(new FileReader(path));
//3. 获取数据,赋值
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
//4. 注册驱动
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 获取连接
* @return 连接对象
*/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, user, password);
}
/**
* 释放资源
* @param stmt
* @param conn
*/
public static void close(Statement stmt,Connection conn){
if( stmt != null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if( conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
JDBCUtils使用
直接使用静态类JDBCUtils静态方法创建连接对象。最后使用该类的close关闭statement、connection、resultset对象
如果需要修改JDBCUtils配置在jdbc.properties进行修改。
案例通过查询user表,实现查询登录功能
步骤分析
- 使用JDBCUtils对象连接数据库
- 查询user数据库表,如果查询有结果,则表示成功登录
代码
/**
* 登录方法
*/
public boolean login(String username ,String password){
if(username == null || password == null){
return false;
}
//连接数据库判断是否登录成功
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
//1.获取连接
try {
conn = JDBCUtils.getConnection();
//2.定义sql
String sql = "select * from user where username = '"+username+"' and password = '"+password+"' ";
//3.获取执行sql的对象
stmt = conn.createStatement();
//4.执行查询
rs = stmt.executeQuery(sql);
//5.判断
/* if(rs.next()){//如果有下一行,则返回true
return true;
}else{
return false;
}*/
return rs.next();//如果有下一行,则返回true
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtils.close(rs,stmt,conn);
}
return false;
}
}
JDBC控制事务
事务概述
一个包含多个步骤的业务,我们期望他要么全部执行成功,要么同时执行失败。
操作
- 开启事务 setAutoCommit(false)
- 成功,手动commit,提交事务
- 失败(捕获到异常),手动rollback,回滚事务
举例
public class JDBCDemo10 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt1 = null;
PreparedStatement pstmt2 = null;
try {
//1.获取连接
conn = JDBCUtils.getConnection();
//开启事务
conn.setAutoCommit(false);
//2.定义sql
//2.1 张三 - 500
String sql1 = "update account set balance = balance - ? where id = ?";
//2.2 李四 + 500
String sql2 = "update account set balance = balance + ? where id = ?";
//3.获取执行sql对象
pstmt1 = conn.prepareStatement(sql1);
pstmt2 = conn.prepareStatement(sql2);
//4. 设置参数
pstmt1.setDouble(1,500);
pstmt1.setInt(2,1);
pstmt2.setDouble(1,500);
pstmt2.setInt(2,2);
//5.执行sql
pstmt1.executeUpdate();
// 手动制造异常
int i = 3/0;
pstmt2.executeUpdate();
//提交事务
conn.commit();
} catch (Exception e) {
//事务回滚
try {
if(conn != null) {
conn.rollback();
}
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally {
JDBCUtils.close(pstmt1,conn);
JDBCUtils.close(pstmt2,null);
}
}
}
参考
1.黑马JDBC笔记