正文
JDBC 基本介绍
1. JDBC 概念
JDBC(Java DataBase Connectivity,Java数据库连接),是一种用于执行 SQL 语句的 Java API ,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC 提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序,同时,JDBC也是个商标名。
JDBC 百度百科
概念解释:
-
定义了一套操作所有关系型数据库的规则(接口)。
-
不同的 JDBC 实现类由不同的厂商实现(数据库驱动),提供驱动数据库的 jar 包。
-
我们可以使用这套 JDBC 编程,正真执行的代码是驱动 jar 包中的实现类。
2. 快速入门
2.1 建表
首先在MySQL数据库中准备一个表供后续的所有操作。
create table account(
id INT PRIMARY KEY AUTO_INCREMENT,
a_name VARCHAR(30),
a_money DOUBLE
);
insert into account(id,a_name,a_money) values
(1,"张三",1000),
(2,"李四",1000);
2.2 代码展示
需要提前导入连接数据库的包,如果没有,参考这篇教程
MySQL驱动下载
。
我这里用的是 MySQL8.0.17 版本,根据自己数据库的安装版本下载对应的驱动。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
public class JdbcDemo {
public static void main(String[] args) throws Exception{
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo_test?serverTimezone=UTC","root","root");
String sql1 = "update account set a_money = 500 where id = 1";
String sql2 = "update account set a_money = 1500 where id = 1";
Statement stmt = conn.createStatement();
int count = stmt.executeUpdate(sql1);
int count2 = stmt.executeUpdate(sql2);
System.out.println(count);
System.out.println(count2);
stmt.close();
conn.close();
}
}
注意:
-
mysql 5.0 注册驱动:com.mysql.jdbc.Driver
-
mysql 5.0 连接数据库:jdbc:mysql://localhost:3306/demo_test
-
mysql 8.0 注册驱动:com.mysql.cj.jdbc.Driver
-
mysql 8.0 连接数据库:dbc:mysql://localhost:3306/demo_test?serverTimezone=UTC
3. JDBC 中各个对象
(
Java.sql 的 API 介绍
)
这里简单介绍几个常用管理对象,具体参照 API 中的介绍。
3.1 DriverManager
用于管理一组JDBC驱动程序的基本服务。
方法
|
描述
|
static Connection getConnection(String url, String user, String password)
|
尝试建立到给定数据库URL的连接。
|
参数解释:
-
url
:指定连接的路径:jdbc:mysql://ip地址(域名):端口号/数据库名称
-
如果连接的是本机 MySQL 服务器,并且 MySQL 服务器默认端口是 3306,则 url 可以简写为:jdbc:mysql:///数据库名称 。
-
user
:数据库连接用户名
-
password
:数据库连接密码
代码应用片段:
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo_test?serverTimezone=UTC","root","root");
3.2 Connection
与特定数据库的连接(会话)。执行SQL语句,并在连接的上下文中返回结果。
方法
|
描述
|
Statement createStatement()
|
创建一个Statement对象,用于将SQL语句发送到数据库。
|
PreparedStatement prepareStatement(String sql)
|
创建一个PreparedStatement对象,用于将参数化的SQL语句发送到数据库
|
void setAutoCommit(boolean autoCommit)
|
将此连接的自动提交模式设置为给定状态。
|
void commit()
|
使自上一次提交/回滚以来的所有更改永久生效,并释放此Connection对象当前持有的所有数据库锁。
|
void rollback()
|
撤消在当前事务中进行的所有更改,并释放此Connection对象当前持有的所有数据库锁。
|
代码应用片段:
Statement stmt = conn.createStatement();
int count = stmt.executeUpdate(sql);
3.3 Statement
用于执行静态SQL语句并返回其产生的结果的对象。
方法
|
描述
|
boolean execute(String sql)
|
执行任意给定的SQL语句,该语句可能返回多个结果。
|
int executeUpdate(String sql)
|
执行DML(insert、update、delete)返回改变行数,或者执行DDL(create、alter、drop)不返回任何内容。
|
ResultSet executeQuery(String sql)
|
执行给定的SQL语句,该语句返回一个 ResultSet对象。
|
代码应用片段:
Statement stmt = null;
int count = stmt.executeUpdate(sql);
int count = stmt.executeUpdate(sql);
ResultSet rs = stmt.executeQuery(sql);
3.4 PreparedStatement
表示
预编译
的 SQL 语句的对象,SQL 语句已预编译并存储在 PreparedStatement 对象中。然后可以使用该对象多次有效地执行该语句。预编译 SQL 时,参数用占位符(?)占位,等应用时再用实际参数替换占位符(?)。
方法
|
描述
|
PreparedStatement Connection.prepareStatement(String sql)
|
创建一个 PreparedStatement对象,用于将参数化的SQL语句发送到数据库。
|
setXXX(参数1,参数2)
|
给预编译SQL语句中的占位符 ? 赋值
|
注意:
-
Xxx 可以为任意基本类型,与数据库中一致。
-
参数1:占位符(?)的位置,从1开始计数
-
参数2:占位符(?)的替换值
代码应用片段:
String sql1 = "update account set a_money = a_money - ? where id = ?";
String sql2 = "update account set a_money = a_money + ? where id = ?";
PreparedStatement pstmt1 = conn.prepareStatement(sql1);
PreparedStatement pstmt2 = conn.prepareStatement(sql2);
pstmt1.setDouble(1,500);
pstmt1.setInt(2,1);
pstmt2.setDouble(1,500);
pstmt2.setInt(2,2);
3.5 ResultSet
代表数据库结果集的数据表,通常通过执行查询数据库的语句来生成。
方法
|
描述
|
boolean next()
|
向后移动游标,判断当前行是否有记录,有则返回 true,反之返回false
|
getXxx()
|
获取Xxx类型的数据
|
关于getXxx()方法的注意事项:
-
Xxx为基本数据类型,如:getString()、getInt()等。
-
参数可以是列的编号或者是列的名称。
代码应用片段
while(resultset.next()){
int id = resultset.getInt(1);
String name = resultset.getString("a_name");
double money = resultset.getDouble(3);
System.out.println(id + "---" + name + "---" + money);
}
4. 抽取 JDBC 的工具类
4.1 目的
简化代码编写,增加代码的可维护性,将 JDBC 的基本操作放到一个工具类中,用配置文件来获取连接信息,降低耦合。
4.2 操作
在一个类中完成注册驱动、获取连接、释放资源等 JDBC 相关操作,抽取一个方法获取连接对象,用配置文件(jdbc.properties)的方式保存连接信息,让工具类具有通用性。
4.3 配置文件的编写
url=jdbc:mysql:///demo_test?serverTimezone=UTC
user=root
password=root
driver=com.mysql.cj.jdbc.Driver
4.4 工具类的编写
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
public class JdbcUtils {
private static String url;
private static String user;
private static String password;
private static String driver;
static {
try {
Properties pro = new Properties();
ClassLoader classLoader = JdbcUtils.class.getClassLoader();
URL res = classLoader.getResource("jdbc.properties");
String path = res.getPath();
System.out.println(path);
pro.load(new FileReader(path));
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
driver = pro.getProperty("driver");
Class.forName(driver);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,user, password);
}
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();
}
}
}
public static void close(ResultSet rs, Statement stmt, Connection conn){
if (rs != null){
try {
rs.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (stmt != null){
try {
stmt.close();
}catch (SQLException e){
e.printStackTrace();
}
}
if (conn != null){
try {
conn.close();
}catch (SQLException e){
e.printStackTrace();
}
}
}
}
5. 综合实例
案例需求:完成张三和李四的转账操作,张三账户 -500 ,李四账户 +500
-
创建数据库
create table account(
id INT PRIMARY KEY AUTO_INCREMENT,
a_name varchar(30),
a_money double
);
insert into account(id,a_name,a_money) values
(1,"张三",1000),
(2,"李四",1000);
select * from account;
-
编写 jdbc.properties 配置文件,放在src目录下。内如参照 JDBC工具类抽取。
-
编写工具类,内容参照 JDBC 工具类抽取。
-
编写主类
package base.jdbc;
import base.util.JdbcUtils;
import java.sql.*;
public class JdbcDemo8 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstmt1 = null;
PreparedStatement pstmt2 = null;
try {
conn = JdbcUtils.getConnection();
conn.setAutoCommit(false);
String sql1 = "update account set a_money = a_money - ? where id = ?";
String sql2 = "update account set a_money = a_money + ? where id = ?";
pstmt1 = conn.prepareStatement(sql1);
pstmt2 = conn.prepareStatement(sql2);
pstmt1.setDouble(1,500);
pstmt1.setInt(2,1);
pstmt2.setDouble(1,500);
pstmt2.setInt(2,2);
pstmt1.executeUpdate();
pstmt2.executeUpdate();
conn.commit();
} catch (Exception e) {
try{
if (conn != null) {
conn.rollback();
}
} catch (SQLException se){
se.printStackTrace();
}
e.printStackTrace();
} finally {
JdbcUtils.close(pstmt1,conn);
JdbcUtils.close(pstmt2,null);
}
}
}
-
再次查询表中内容
select * from account;
时间:2019年10月29日19:17:36