JDBC事务管理
由于每一次连接数据库进行操作都要获取连接,关闭接口等,这样代码重复度很高,所以我们可以写一个工具类来帮我们做这些,这样代码就会简洁很多。
首先创建配置文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
user=root
password=123456
创建工具类
import java.io.FileReader;
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;
private JDBCUtils() {};
/**
* 文件的读取只需要读一次即可拿到这些值,使用静态代码块
*/
static {
// 读取资源文件
try {
// 创建properties集合类
Properties pro = new Properties();
// 获取src路径下的文件的方式,ClassLoader类加载器,随便用一个src下的类的字节码文件
ClassLoader classLoader = JDBCUtils.class.getClassLoader();
// URL表示一个统一资源标识符(统一资源定位符),这个统一资源定位符可以定位一个文件的绝对路径
URL resource = classLoader.getResource("jdbc.properties");
// 获取该文件的绝对路径
String path = resource.getPath();
// 加载文件
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 (Exception e) {
e.printStackTrace();
}
}
/**
* 获取连接对象
* 需求:不想传递参数(麻烦,还没有源代码简洁),还得保证工具类的通用性
* @return 连接对象
*/
public static Connection getConnection() throws Exception {
return DriverManager.getConnection(url, user, password);
}
/**
* 释放资源
* @param statement sql执行语句对象
* @param connection 连接对象
*/
public static void close(Statement statement, Connection connection) {
close(null, statement, connection);
}
/**
* 释放资源
* @param resultSet 结果集对象
* @param statement sql执行语句对象
* @param connection 连接对象
*/
public static void close(ResultSet resultSet, Statement statement, Connection connection) {
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
else if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
-
使用Connection对象来管理事务
- 开启事务:setAutoCommit(boolean autoCommit) :调用该方法设置参数为false,即开启事务
- 提交事务:commit()
- 回滚事务:rollback()
-
在执行sql语句之前开启事务connection.setAutoCommit(false);,出现异常就在catch代码块中使用connection.rollback();回滚事务,正常结束就在try代码块中使用connection.commit();提交事务。
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class JdbcTransferAccounts {
public static void main(String[] args) {
Connection connection = null;
PreparedStatement prepared1 = null;
PreparedStatement prepared2 = null;
try {
// 使用我们自己创建的工具类获取连接
connection = JDBCUtils.getConnection();
// 开启事务
connection.setAutoCommit(false);
// 定义sql语句
String sql1 = "update account set balance = balance - ? where id = ?";
String sql2 = "update account set balance = balance + ? where id = ?";
// 获取执行sql对象
prepared1 = connection.prepareStatement(sql1);
prepared2 = connection.prepareStatement(sql2);
// 设置参数
prepared1.setDouble(1, 5000);
prepared1.setInt(2, 1);
prepared2.setDouble(1, 5000);
prepared2.setInt(2, 2);
// 执行sql
prepared1.executeUpdate();
// 手动制造一个异常,使prepared2.executeUpdate();无法执行,方便测试观察事务
// int a = 3 / 0;
prepared2.executeUpdate();
// 提交事务
connection.commit();
} catch (Exception e) {
try {
// 出现异常,回滚事务
if (connection != null) connection.rollback();
} catch (Exception ex) {
ex.printStackTrace();
}
e.printStackTrace();
} finally {
// 释放资源
JDBCUtils.close(prepared1, connection);
JDBCUtils.close(prepared2, null);
}
}
}