1. JDBC 的相关 API 小结 832
2. 封装 JDBCUtils 【关闭连接, 得到连接】 833
2.1 说明
在jdbc操作中,获取连接和释放资源是经常使用到可以将其封装JDBC连接的具类JDBCUtils
2.2 代码实现
实际使用使用工具类 JDBCUtils
代码在com.stulzl.utils.
JDBCUtils 833
package com.stulzl.utils;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;
//这是一个工具类,完成 mysql 的连接和关闭资源 833
public class JDBCUtils {
//定义相关的属性(4 个), 因为只需要一份,因此,我们做出 static
private static String user; //用户名
private static String password; //密码
private static String url; //url
private static String driver; //驱动名
//再static代码块中去初始化
static{
try {
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//读取相关的属性数据
user = properties.getProperty("user");
password = properties.getProperty("password");
url = properties.getProperty("url");
driver = properties.getProperty("driver");
} catch (IOException e) {
//在实际开发中,我们可以这样处理
//1. 将编译异常转成 运行异常
//2. 调用者,可以选择捕获该异常,也可以选择默认处理该异常,比较方便.
throw new RuntimeException(e);
}
}
//连接数据库,返回Connection
public static Connection getConnection(){
try {
return DriverManager.getConnection(url,user,password);
} catch (SQLException e) {
//1. 将编译异常转成 运行异常
//2. 调用者,可以选择捕获该异常,也可以选择默认处理该异常,比较方便.
throw new RuntimeException(e);
}
}
//关闭相关资源
//分析可能要关闭的资源
/*
1. ResultSet 结果集
2. Statement 或者 PreparedStatement
3. Connection
4. 如果需要关闭资源,就传入对象,否则传入 null
*/
public static void close(ResultSet set, Statement statement,Connection connection){
try {
//判断是否为null
if(set!=null){
set.close();
}
if(statement!=null){
statement.close();
}
if(connection!=null){
connection.close();
}
} catch (SQLException e) {
//1. 将编译异常转成 运行异常
//2. 调用者,可以选择捕获该异常,也可以选择默认处理该异常,比较方便.
throw new RuntimeException(e);
}
}
}
测试类JDBCUtils_Use 834
package com.stulzl.utils;
import org.junit.jupiter.api.Test;
import javax.annotation.processing.SupportedAnnotationTypes;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
//该类演示如何使用JDBCUtils工具类,完成dml和select 834
public class JDBCUtils_Use {
public static void main(String[] args) {
}
@Test
public void testDML(){
//1.得到连接
Connection connection = null;
//2.组织一个sql语句
String sql = "update actor set name=? where id = ?";
PreparedStatement preparedStatement=null;
try {
connection = JDBCUtils.getConnection();
//3.创建preparedStatement对象
preparedStatement = connection.prepareStatement(sql);
//4. 给占位符赋值
preparedStatement.setString(1,"周星驰");
preparedStatement.setInt(2,2);
//执行
preparedStatement.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭资源
JDBCUtils.close(null,preparedStatement,connection);
}
}
}
配置文件再src下面 mysql.properties
user=root
password=lzl
url=jdbc:mysql://localhost:3306/hsp_db02
driver=com.mysql.jdbc.Driver
2.2.1 JDBCUtils的select使用 835
testSelect()方法
//JDBCUtils的select使用 835
@Test
public void testSelect(){
//1.得到连接
Connection connection = null;
//2.组织一个sql语句
String sql = "select * from actor where id=?";
PreparedStatement preparedStatement=null;
ResultSet set = null;
try {
connection = JDBCUtils.getConnection();
//3.创建preparedStatement对象
preparedStatement = connection.prepareStatement(sql);
//4. 给占位符赋值
preparedStatement.setInt(1,2);
//执行,得到结果集
set = preparedStatement.executeQuery();
//遍历该结果集
while(set.next()){
int id = set.getInt("id");//这里提示("id")可以直接写,也可以写数字(按对应顺序)
String name = set.getString("name");
String sex = set.getString("sex");
Date borndate = set.getDate("borndate");
String phone = set.getString("phone");
System.out.println(id + "\t" + name + "\t" + sex
+ "\t" + borndate + "\t" + phone);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭资源
JDBCUtils.close(set,preparedStatement,connection);
}
}
}
3. 事务 836
3.1 基本介绍 836
1. JDBC程序中当一 个Connection对象创建时,默认情况下是自动提交事务:每次执行一个SQL语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
2. JDBC程序中为了让多个 SQL语句作为一个整体执行,需要使用事务
3.调用Connection的setAutoCommit(false)可以取消自动提交事务
4.在所有的SQL语询都成功执行后,调用Connection的commit();方法提交事务
5.在其中某个操作失败或出现异常时, 调用Connection的rollback();方法回滚事务
3.2 应用实例 837
模拟经典的转账业务
3.3 不使用事务可能出现的问题模拟-模拟经典的转账业务 837
3.4 使用事务解决上述问题-模拟经典的转账业务 837
3.3和3.4代码在 com.stulzl.transaction_
Transaction_
package com.stulzl.transaction_;
import com.stulzl.utils.JDBCUtils;
import org.junit.jupiter.api.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
//演示JDBC中如何使用事务 837
public class Transaction_ {
//不使用事务
@Test
public void noTransaction(){
//1.得到连接
Connection connection = null;
//2.组织一个sql语句
String sql = "update account1 set balance=balance-100 where id = 1";
String sql2 = "update account1 set balance=balance+100 where id = 2";
PreparedStatement preparedStatement=null;
try {
connection = JDBCUtils.getConnection();// 在默认情况下,connection 是默认自动提交
//3.创建preparedStatement对象
//这里就是给马云扣100
preparedStatement = connection.prepareStatement(sql);
preparedStatement.executeUpdate();//执行第一条sql
//这里抛出异常,我们的目的是为了让马云转账出去,但是马化腾接收不到(因为执行遇到异常后
// 面的代码将不再运行) 让我们更加直观的感受接下来事务操作
int i = 1/0;
//这里就是给马化腾加100
preparedStatement = connection.prepareStatement(sql2);
preparedStatement.executeUpdate();//执行第二条sql2
} catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭资源
JDBCUtils.close(null,preparedStatement,connection);
}
}
//使用事务来解决
@Test
public void useTransaction(){
//1.得到连接
Connection connection = null;
//2.组织一个sql语句
String sql = "update account1 set balance=balance-100 where id = 1";
String sql2 = "update account1 set balance=balance+100 where id = 2";
PreparedStatement preparedStatement=null;
try {
connection = JDBCUtils.getConnection();// 在默认情况下,connection 是默认自动提交
//将connection设置为不自动提交
connection.setAutoCommit(false);//相当于开启了事务
//3.创建preparedStatement对象
//这里就是给马云扣100
preparedStatement = connection.prepareStatement(sql);
preparedStatement.executeUpdate();//执行第一条sql
//int i = 1/0;//这里抛出异常
//这里就是给马化腾加100
preparedStatement = connection.prepareStatement(sql2);
preparedStatement.executeUpdate();//执行第二条sql2
//这里提交事务
connection.commit();
} catch (SQLException e) {
//这里我们可以进行回滚,即撤销执行的 SQL
//默认回滚到事务开始的状态
System.out.println("执行发生了异常,撤销执行的 sql");
try {
connection.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
e.printStackTrace();
} finally {
//关闭资源
JDBCUtils.close(null,preparedStatement,connection);
}
}
}
代码在E:\java学习\初级\course170\db_
java_transaction
-- 创建表 837
CREATE TABLE account1(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(32) NOT NULL DEFAULT'',
balance DOUBLE NOT NULL DEFAULT 0) CHARACTER SET utf8;
-- 添加数据
INSERT INTO account1 VALUES(NULL, '马云',3000);
INSERT INTO account1 VALUES(NULL, '马化腾',10000);
SELECT * FROM account1