JDBC学习
文章目录
1. JDBC
- java DataBase Connectivity Java数据库连接
- 使用java语言操作数据库
1.1 JDBC的本质
-
一套操作所有关系型数据库的规则,即接口,各个数据库厂商写出不同的jar包去调用这套接口,真正执行的代码是驱动jar包中的实现类
-
图解
1.2 java连接数据库
- 步骤:
1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
1.复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下
2.右键–>Add As Library
2. 注册驱动
3. 获取数据库连接对象 Connection
4. 定义sql
5. 获取执行sql语句的对象 Statement
6. 执行sql,接受返回结果
7. 处理结果
8. 释放资源
代码示例
package codes;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import static java.lang.Class.forName;
public class Demo1 {
public static void main(String[] args) throws Exception {
/*
mysql 5 之后的jar包可以省略不写 注册驱动这行代码
E:\JavaWebCodes\javaweb_day05\day05_jdbc\libs\mysql-connector-java-5.1.37-bin.jar!\
META-INF\services\
java.sql.Driver
这个配置文件里面写了
*/
//注册驱动
Class.forName("com.mysql.jdbc.Driver");
/*
Driver 源码,类加载进来时自动执行,且执行一次
实际执行对象未 DriverManager
static {
try {
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
*/
//获取数据库连接对象
Connection cont = DriverManager.getConnection("jdbc:mysql://localhost:3306/db3", "root", "root");
// 定义1条sql语句
String sql="update account set balance=500 where id=1";
// 获取执行sql的语句的对象
Statement stat = cont.createStatement();
// 执行sql语句
int result = stat.executeUpdate(sql);
System.out.println(result);
// 关闭资源
stat.close();
cont.close();
}
}
1.3 各个对象的详细解释
-
DriverManager:驱动管理对象
* 功能:
1. 注册驱动:告诉程序该使用哪一个数据库驱动jar
static void registerDriver(Driver driver) :注册与给定的驱动程序 DriverManager 。
写代码使用: Class.forName(“com.mysql.jdbc.Driver”);
通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块**
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException(“Can’t register driver!”);
}
}**注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。 2. 获取数据库连接: * 方法:static Connection getConnection(String url, String user, String password) * 参数: * url:指定连接的路径 * 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称 * 例子:jdbc:mysql://localhost:3306/db3 * 细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称 * user:用户名 * password:密码
- Connection:数据库连接对象
- 功能:
- 获取执行sql 的对象
- Statement createStatement()
- PreparedStatement prepareStatement(String sql)
- 管理事务:
- 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
- 提交事务:commit()
- 回滚事务:rollback()
- 获取执行sql 的对象
- 功能:
- Statement:执行sql的对象
- 执行sql
- boolean execute(String sql) :可以执行任意的sql 了解
- int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句
- 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。
- ResultSet executeQuery(String sql) :执行DQL(select)语句
- 练习:
- account表 添加一条记录
- account表 修改记录
- account表 删除一条记录
- 执行sql
- Connection:数据库连接对象
1.4 练习的规范示例
- 插入操作
package codes;
/*
执行sql的插入语句
insert into account values(null,"王五","700");
*/
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBC_insert {
public static void main(String[] args) {
Connection cont=null;
Statement stat=null;
try {
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 连接服务器对象
cont = DriverManager.getConnection("jdbc:mysql:///db3","root","root");
// 获取statment对象
stat = cont.createStatement();
// 定义一条mysql语句
String sql=" insert into account values(null,\"王五\",\"700\")";
// 执行sql语句
int count = stat.executeUpdate(sql);
if(count>0){
System.out.println("sql添加成功");
}else{
System.out.println("添加失败");
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
// 释放资源
if(stat!=null){
try {
stat.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(cont!=null){
try {
cont.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
- 修改操作
package codes;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/*
执行一条update 的mysql语句
update account set balance=800 where id=3;
*/
public class JDBC_update {
public static void main(String[] args) {
Connection cont=null;
Statement stat=null;
try {
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 连接数据库对象
cont = DriverManager.getConnection("jdbc:mysql:///db3","root","root");
// 获取执行sql的对象
stat = cont.createStatement();
// 定义一条修改语句
String sql="update account set balance=800 where id=3";
// 执行sql语句
int count = stat.executeUpdate(sql);
if(count>0){
System.out.println("sql执行成功");
}else{
System.out.println("sql执行失败");
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally{
// 释放资源
if(stat!=null){
try {
stat.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(cont!=null){
try {
cont.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
- 删除操作
package codes;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/*
执行一条删除的mysql语句
delete from account where id=3;
*/
public class JDBC_delete {
public static void main(String[] args) {
Connection cont=null;
Statement stat=null;
try {
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 连接数据库对象
cont = DriverManager.getConnection("jdbc:mysql:///db3","root","root");
// 创建一个statment对象
stat = cont.createStatement();
// 定义一条删除的sql语句
String sql="delete from account where id=3";
// 执行sql语句
int cnt = stat.executeUpdate(sql);
if(cnt>0){
System.out.println("sql执行成功");
}else{
System.out.println("sql执行失败");
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
if(stat!=null){
try {
stat.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
if(cont!=null){
try {
cont.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
- DDL语句
package codes;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/*
* 执行一条DDL语句,创建一个新的学生表stu5
* create table stu5(id int,name varchar(20));
*/
public class JDBC_DDL {
public static void main(String[] args) {
Connection cont=null;
Statement stat=null;
try {
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 连接数据库对象
cont = DriverManager.getConnection("jdbc:mysql:///db3","root","root");
// 执行mysql的对象
stat = cont.createStatement();
// 定义一条DDL语句
String ddl="create table stu5(id int,name varchar(20))";
// 执行sql语句
int cnt = stat.executeUpdate(ddl);
System.out.println(cnt);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
if(stat!=null){
try {
stat.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(cont!=null){
try {
cont.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
1.5 结构集对象(封装DQL的查询结果)
-
ResultSet:结果集对象,封装查询结果
-
next():游标向下移动一行
-
getXxx(参数)::获取数据,某一行的某一列(一个单元格)
- Xxx:代表数据类型,如int getInt() ,String getString()
- 参数
- int:代表列的编号,从1开始,如getString(1)
- String:代表列的名称,如getDouble(“balance”)
-
注意:
* 使用步骤:
1. 游标向下移动一行
2. 判断是否有数据
3. 获取数据//循环判断游标是否是最后一行末尾。 while(rs.next()){ //获取数据 //6.2 获取数据 int id = rs.getInt(1); String name = rs.getString("name"); double balance = rs.getDouble(3); System.out.println(id + "---" + name + "---" + balance); }
-
示例
package codes;
import java.sql.*;
public class JDBC_ResultSet {
public static void main(String[] args) {
Connection cont=null;
Statement stat=null;
ResultSet rs=null;
try {
// 加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 链接数据库
cont = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
//创建执行sql语句的对象
stat = cont.createStatement();
// 定义一条sql语句(DQL)
String sql="select *from account";
rs = stat.executeQuery(sql);
rs.next();
// 获取id
int id = rs.getInt(1);
// 获取姓名
String name=rs.getString("name");
// 获取余额balance
double balance = rs.getDouble("balance");
System.out.println(id+"---"+name+"---"+balance);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
// 释放资源
if(rs!=null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(stat!=null){
try {
stat.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(cont!=null){
try {
cont.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
- 效果图
示例:打印表中所有数据
package codes;
import java.sql.*;
public class JDBC_ResultSet_for {
public static void main(String[] args) {
Connection cont=null;
Statement stat=null;
ResultSet rs=null;
try {
// 加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 链接数据库
cont = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
//创建执行sql语句的对象
stat = cont.createStatement();
// 定义一条sql语句(DQL)
String sql="select *from account";
rs = stat.executeQuery(sql);
//循环判读释放存在下一行,如果存在,循环打印,不存在,终止
while(rs.next()){
// 获取id
int id = rs.getInt(1);
// 获取姓名
String name=rs.getString("name");
// 获取余额balance
double balance = rs.getDouble("balance");
System.out.println(id+"---"+name+"---"+balance);
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
// 释放资源
if(rs!=null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(stat!=null){
try {
stat.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(cont!=null){
try {
cont.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
}
- 效果图
1.6 练习:将表中的记录转换成对象存储
- 练习:
* 定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,返回。
1. 定义Emp类
2. 定义方法 public List getData(){}
3. 实现方法 select * from emp;
- 员工表
- 创建员工类
package someclass;
/*
* 员工类
* 存放数据库中的员工记录
*/
import java.util.Date;
public class Emp {
private int id;
private String ename;
private int job_id;
private int mgr;
private Date joindate;
private double salary;
private double bonus;
private int dept_id;
public Emp() {
}
public Emp(int id, String ename, int job_id, int mgr, Date joindate, double salary, double bonus, int dept_id) {
this.id = id;
this.ename = ename;
this.job_id = job_id;
this.mgr = mgr;
this.joindate = joindate;
this.salary = salary;
this.bonus = bonus;
this.dept_id = dept_id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public int getJob_id() {
return job_id;
}
public void setJob_id(int job_id) {
this.job_id = job_id;
}
public int getMgr() {
return mgr;
}
public void setMgr(int mgr) {
this.mgr = mgr;
}
public Date getJoindate() {
return joindate;
}
public void setJoindate(Date joindate) {
this.joindate = joindate;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
public int getDept_id() {
return dept_id;
}
public void setDept_id(int dept_id) {
this.dept_id = dept_id;
}
@Override
public String toString() {
return "Emp{" +
"id=" + id +
", ename='" + ename + '\'' +
", job_id=" + job_id +
", mgr=" + mgr +
", joindate=" + joindate +
", salary=" + salary +
", bonus=" + bonus +
", dept_id=" + dept_id +
'}';
}
}
- 创建转换方法
package codes;
import someclass.Emp;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/*
* 将员工表中的记录转换成对象,存储起来
*/
public class JDBC_DQL_emp {
public static void main(String[] args) {
List<Emp> data = new JDBC_DQL_emp().getData();
for (Emp emp : data) {
System.out.println(emp);
}
}
public static List<Emp> getData(){
Connection cont=null;
Statement stat=null;
ResultSet rs=null;
ArrayList<Emp> empLists = new ArrayList<>();
try {
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 连接数据库
cont = DriverManager.getConnection("jdbc:mysql:///db3","root","root");
// 创建sql执行对象
stat = cont.createStatement();
// 定义一个sql语句
String sql="select *from emp";
rs = stat.executeQuery(sql);
Emp emp = new Emp();
while(rs.next()){
int id = rs.getInt("id");
String ename = rs.getString("ename");
int job_id = rs.getInt("job_id");
int mgr = rs.getInt("mgr");
Date joindate = rs.getDate("joindate");
double salary = rs.getDouble("salary");
double bonus = rs.getDouble("bonus");
int dept_id = rs.getInt("dept_id");
emp = new Emp();
emp.setId(id);
emp.setEname(ename);
emp.setJob_id(job_id);
emp.setJoindate(joindate);
emp.setSalary(salary);
emp.setBonus(bonus);
emp.setDept_id(dept_id);
emp.setMgr(mgr);
empLists.add(emp);
}
return empLists;
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}finally {
if(rs!=null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(stat!=null){
try {
stat.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(cont!=null){
try {
cont.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
return empLists;
}
}
- 效果图
1.7 优化sql语句的操作
- 写一个JDBC的工具类,来简化一些重复的操作
- 注册驱动
- 连接数据库
- 释放资源
- 配置文件:用于连接数据库,存储user,password,数据库名称
url=jdbc:mysql:///db3
user=root
password=root
driver=com.mysql.jdbc.Driver
- 工具类
package JDBC_Utils;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;
/*
**`连接数据库的一些工具类
* 1.注册取得
* 2.获取连接对象
* 3.释放资源
*/
public class JDBC_tools {
private static String url;
private static String user;
private static String password;
private static String driver;
/*
创建一个静态代码块,在类加载的时候只执行一次
加载配置文件
*/
static{
// 配置文件流
Properties pro=new Properties();
// 定义一个类加载器,
ClassLoader cls = JDBC_tools.class.getClassLoader();
// 获取文件的URL
URL resource = cls.getResource("jdbc.properties");
// URL的路径部分
String path = resource.getPath();
try {
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 | ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,user,password);
}
/**
* 释放连接对象cont和执行sql对象stat
* 适用于DML,DDL的情况
* @param cont
* @param stat
*/
public static void closeSource(Connection cont, Statement stat){
if(stat!=null){
try {
stat.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(cont!=null){
try {
cont.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
/**
* 释放连接对象cont和执行sql对象stat和结果集对象rs
* 适用于DQL的情况
* @param cont
* @param stat
* @param rs
*/
public static void closeSource(Connection cont, Statement stat,ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(stat!=null){
try {
stat.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
if(cont!=null){
try {
cont.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
- 测试类
package codes;
import JDBC_Utils.JDBC_tools;
import someclass.Emp;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/*
* 将员工表中的记录转换成对象,存储起来
*/
public class JDBC_DQL_emp_tools {
public static void main(String[] args) {
List<Emp> data = new JDBC_DQL_emp().getData();
for (Emp emp : data) {
System.out.println(emp);
}
}
public static List<Emp> getData(){
Connection cont=null;
Statement stat=null;
ResultSet rs=null;
ArrayList<Emp> empLists = new ArrayList<>();
try {
//使用工具类的方法
// 连接数据库
cont = JDBC_tools.getConnection();
// 创建sql执行对象
stat = cont.createStatement();
// 定义一个sql语句
String sql="select *from emp";
rs = stat.executeQuery(sql);
Emp emp = new Emp();
while(rs.next()){
int id = rs.getInt("id");
String ename = rs.getString("ename");
int job_id = rs.getInt("job_id");
int mgr = rs.getInt("mgr");
Date joindate = rs.getDate("joindate");
double salary = rs.getDouble("salary");
double bonus = rs.getDouble("bonus");
int dept_id = rs.getInt("dept_id");
emp = new Emp();
emp.setId(id);
emp.setEname(ename);
emp.setJob_id(job_id);
emp.setJoindate(joindate);
emp.setSalary(salary);
emp.setBonus(bonus);
emp.setDept_id(dept_id);
emp.setMgr(mgr);
empLists.add(emp);
}
return empLists;
} catch ( SQLException e) {
e.printStackTrace();
}finally {
//使用工具类的方法
JDBC_tools.closeSource(cont,stat,rs);
}
return empLists;
}
}
- 效果图
1.8 练习:数据库登录案例
- 练习:
-
需求:
- 通过键盘录入用户名和密码
- 判断用户是否登录成功
- select * from user where username = “” and password = “”;
- 如果这个sql有查询结果,则成功,反之,则失败
-
步骤:
- 创建数据库表 user(在数据库db4创建)
CREATE TABLE USER( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(32), PASSWORD VARCHAR(32) INSERT INTO USER VALUES(NULL,'zhangsan','123'); INSERT INTO USER VALUES(NULL,'lisi','234'); );
- 使用工具类,注意修改配置文件
url=jdbc:mysql:///db4 user=root password=root driver=com.mysql.jdbc.Driver
- java测试代码
package codes; import JDBC_Utils.JDBC_tools; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Scanner; public class JDBC_Login { public static void main(String[] args) { Scanner sc=new Scanner(System.in); System.out.println("请输入用户名:"); String username=sc.nextLine(); System.out.println("请输入密码:"); String password=sc.nextLine(); boolean result = new JDBC_Login().login(username, password); if(result){ System.out.println("登录成功"); }else{ System.out.println("用户名或密码错误"); } } public static boolean login(String username,String password){ Connection cont=null; Statement stat=null; ResultSet rs=null; try { // 使用工具类,实现驱动注册,连接数据库 cont = JDBC_tools.getConnection(); // 获取指向sql的对象 stat = cont.createStatement(); // 定义sql语句,用于查找用户输入的用户名和密码 String sql="select *from user where username='"+username +"' and password='"+ password+"'"; rs = stat.executeQuery(sql); // 查询到了,为true,查询不到,为false return rs.next(); } catch (SQLException throwables) { throwables.printStackTrace(); }finally { JDBC_tools.closeSource(cont,stat,rs); } return false; } }
- 效果图
-
1.9 sql注入问题
-
- SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题
-
输入用户随便,输入密码:a’ or ‘a’ = 'a
2. sql:select * from user where username = ‘fhdsjkf’ and password = ‘a’ or ‘a’ = ‘a’2. 解决sql注入问题:使用PreparedStatement对象来解决 3. 预编译的SQL:参数使用?作为占位符 4. 步骤: 1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar 2. 注册驱动 3. 获取数据库连接对象 Connection 4. 定义sql * 注意:sql的参数使用?作为占位符。 如:select * from user where username = ? and password = ?; 5. 获取执行sql语句的对象 PreparedStatement Connection.prepareStatement(String sql) 6. 给?赋值: * 方法: setXxx(参数1,参数2) * 参数1:?的位置编号 从1 开始 * 参数2:?的值 7. 执行sql,接受返回结果,不需要传递sql语句 8. 处理结果 9. 释放资源 5. 注意:后期都会使用PreparedStatement来完成增删改查的所有操作 1. 可以防止SQL注入 2. 效率更高
- sql注入问题效果图
1.10 解决sql注入问题,提高安全性
package codes;
import JDBC_Utils.JDBC_tools;
import java.sql.*;
import java.util.Scanner;
public class JDBC_Login {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("请输入用户名:");
String username=sc.nextLine();
System.out.println("请输入密码:");
String password=sc.nextLine();
boolean result = new JDBC_Login().login2(username, password);
if(result){
System.out.println("登录成功");
}else{
System.out.println("用户名或密码错误");
}
}
/**
* 解决sql问题,使用prepare
* @param username
* @param password
* @return
*/
public static boolean login2(String username,String password){
Connection cont=null;
PreparedStatement pstat=null;
ResultSet rs=null;
try {
// 使用工具类,实现驱动注册,连接数据库
cont = JDBC_tools.getConnection();
// 获取指向sql的对象
// 使用 PreparedStatement对象来解决sql注入的问题
// 设置一条预编译的sql语句,?为占位符,
String sql="select *from user where username=? and password=?";
pstat=cont.prepareStatement(sql);
// 第一个问号占位符设置字符串数据
pstat.setString(1,username);
// 第二个问号占位符设置字符串数据
pstat.setString(2,password);
//不需要sql参数
rs = pstat.executeQuery();
// 查询到了,为true,查询不到,为false
return rs.next();
} catch (SQLException throwables) {
throwables.printStackTrace();
}finally {
JDBC_tools.closeSource(cont,pstat,rs);
}
return false;
}
}
- 效果图
1.11 事务操作
- 事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则这多个步骤要么同时成功,要么同时失败。
- 操作:
- 开启事务
- 提交事务
- 回滚事务
- 使用Connection对象来管理事务
- 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
- 在执行sql之前开启事务
- 提交事务:commit()
- 当所有sql都执行完提交事务
- 回滚事务:rollback()
- 在catch中回滚事务
- 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
- 代码实现
package codes;
import JDBC_Utils.JDBC_tools;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* JDBC事务操作
* 张三+500
* 李四-500
*/
public class JDBC_things {
public static void main(String[] args) {
// 修改配置文件db3
Connection cont=null;
PreparedStatement pstat1=null;
PreparedStatement pstat2=null;
try {
// 使用工具类
cont = JDBC_tools.getConnection();
// 开启事务
cont.setAutoCommit(false);
// 定义两条sql语句,实现转账
String sq1="update account set balance=balance-? where id=?";
String sq2="update account set balance=balance+? where id=?";
// 使用PreparedStatement执行sql,防止注入
pstat1 = cont.prepareStatement(sq1);
pstat1.setDouble(1,500);
pstat1.setInt(2,1);
pstat2 = cont.prepareStatement(sq2);
pstat2.setDouble(1,500);
pstat2.setInt(2,2);
// 执行sql
pstat1.executeUpdate();
// 人为制造异常
//int num=3/0;
pstat2.executeUpdate();
// 提交事务
cont.commit();
// 抓一个大异常,什么异常发生了,都需要回滚
} catch (Exception throwables) {
// 发生异常,回滚事务
if(cont!=null){
try {
cont.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
throwables.printStackTrace();
}finally {
// 需要释放pstat1 和 pstat2
JDBC_tools.closeSource(cont,pstat1);
JDBC_tools.closeSource(null,pstat2);
}
}
}
- 发生异常的效果图
- 无异常发生