JDBC连接数据库将方法封装优化并且使用事务


前言

JDBC是一种用于Java语言连接数据库的API,它提供了一组用于访问和处理各种关系型数据库的接口和类。在使用JDBC连接数据库时,我们可以将连接数据库的方法进行封装,以便于在其他地方进行重用和调用。
方法封装可以将连接数据库的一系列步骤进行抽象和简化,使得我们在使用时只需要调用一个简单的方法即可完成连接。例如,我们可以将连接数据库的方法封装成一个getConnection()方法,该方法接受数据库连接参数作为输入,然后返回一个Connection对象,这个对象可以用来执行SQL语句和操作数据库。
通过将JDBC连接数据库的方法进行封装,我们可以提高代码的可维护性和可读性,减少重复代码的出现,同时还可以降低代码的耦合度。这样,在开发过程中,我们可以更加专注于业务逻辑的实现,而不需要关注底层的数据库连接细节。


一、如何封装getConnection方法?

1.创建工具DruidUtil类

首先,我们在scr目录下创建一个名为util的模块来存放我们的工具类。

之后在该模块下创建一个名为DruidUtil类的java文件。(这里我使用的名称是JdbcUtil)

2.编写我们的工具类

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

//用于加载连接,对外提供获取连接和回收连接的方法
//利用线程本地变量,存储连接信息,确保一个线程的多个方法可以获取同一个Connection
//优势:事务操作的时候 service 和 dao 属于同一个线程,不用传递参数
//它们可以调用getConnection主动获取相同的连接池
public class JdbcUtil {
    private static DataSource dataSource = null;

    private static ThreadLocal<Connection> thread = new ThreadLocal<>();

    static {
        //初始化连接池对象
        Properties properties = new Properties();
        InputStream resourceAsStream = JdbcUtil.class.getClassLoader().getResourceAsStream("druid.properties");
        try {
            properties.load(resourceAsStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        try {
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static Connection getConnection() throws SQLException {
        //查询线程本地是否存在connection
        Connection connection = thread.get();

        //是否第一次调用
        if (connection == null) {
            //线程本地没有,从连接池获取
            connection = dataSource.getConnection();
            thread.set(connection);
        }
        return connection;
    }

    public static void freeConnection() throws SQLException {
        Connection connection = thread.get();

        if (connection != null) {
            //清空线程本地变量
            thread.remove();
            //事务状态重置
            connection.setAutoCommit(true);
            //回收连接
            connection.close();
        }
    }
}

我们这样做的目的是为了利用线程本地变量,存储连接信息,确保一个线程的多个方法可以获取同一个Connection,这样就可以确保同一个线程内的其他方法调用getConnection方法时获得的connection是同一个对象,这样可以使我们的方法不用相互传递参数,大大优化了代码的运行效率。

二、如何使用这个工具类呢?

//获得连接
 Connection connection = DruidUtil.getConnection();

//回收连接
DruidUtil.freeConnection();

上述两种方法分别是调用获得连接的方法和回收连接的方法,有这两种方法后,你就可以将代码中方法内申请获取连接的内容由代码进行替换了。
例如:

public void add() throws Exception {
        //1.注册驱动
        DriverManager.registerDriver(new Driver());
        //2.获取连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/atguigu","root","123456");

        //开启事务
        try {
            //关闭事务的自动提交
            connection.setAutoCommit(false);

            //传入连接,并执行操作
            bookDao.addBook();

            //提交事务
            connection.commit();
        }catch (Exception e){
            //事务回滚
            connection.rollback();

            //抛出异常
            throw e;
        }finally {
            //回收资源
            JdbcUtil.freeConnection();
        }
    }
}

修改后的代码:

public void add() throws Exception {
        //获取连接
        Connection connection = DruidUtil.getConnection();

        //开启事务
        try {
            //关闭事务的自动提交
            connection.setAutoCommit(false);

            //传入连接,并执行操作
            bookDao.addBook();

            //提交事务
            connection.commit();
        }catch (Exception e){
            //事务回滚
            connection.rollback();

            //抛出异常
            throw e;
        }finally {
            //回收资源
            JdbcUtil.freeConnection();
        }
    }

不仅如此,dao层内的方法一样可以进行替换,这里就不多叙述了。

三.如何引入事务呢?

1.明白什么是事务

事务是指数据库中的一个操作序列,这些操作要么全部执行成功,要么全部失败回滚,以保证数据库的一致性和完整性。在事务中,多个操作被视为一个整体,只有在整个事务执行成功后,才会将数据持久化到数据库中。如果在事务执行过程中出现错误,所有的操作将会回滚,撤销之前的所有操作,使数据库回到操作之前的状态。事务通常用于保证数据库中的数据完整性,避免数据的不一致和错误。

2.事务用代码实现

相信很多小伙伴在看到上述代码块后都发现了开启事务这个注释,我们将其展示在下方。

   //开启事务
        try {
            //关闭事务的自动提交
            connection.setAutoCommit(false);

            //传入连接,并执行操作
            bookDao.addBook();

            //提交事务
            connection.commit();
        }catch (Exception e){
            //事务回滚
            connection.rollback();

            //抛出异常
            throw e;
        }

其实开启事务非常简单,我们只需要关闭自动提交模式。在执行事务操作之前,需要通过设置Connection的setAutoCommit方法将其设置为false,以便手动控制事务提交和回滚。

 //关闭事务的自动提交
connection.setAutoCommit(false);

 //提交事务
connection.commit();

//事务回滚
connection.rollback();

看到这里,可能就有小伙伴要问到了,你这关闭了事务的自动提交,我后面要手动开启吗?
其实不然,我们创建的DruidUtil工具类的回收连接就已经帮我们开启了事务的自动提交了。

public static void freeConnection() throws SQLException {
        Connection connection = thread.get();

        if (connection != null) {
            //清空线程本地变量
            thread.remove();
            //事务状态重置
            connection.setAutoCommit(true);
            //回收连接
            connection.close();
        }
    }

总结

对JDBC连接数据库方法的封装可以提高代码的可读性和可维护性。通常情况下,我们可以通过创建一个数据库工具类来封装JDBC连接,然后在应用程序中通过调用该类的方法来实现数据库连接。通过封装,可以将数据库连接细节隐藏在方法内部,使得在调用该方法时不需要关心具体的实现细节,只需要传入必要的参数即可。这样可以大大减少重复的代码,并且让代码更加简洁易读。
另外,封装JDBC连接方法还可以提高代码的安全性和稳定性。通过在方法内部进行异常处理和资源释放,可以避免一些常见的错误和漏洞,从而提高程序的稳定性和安全性。同时,封装还可以方便地实现对数据库连接的统一管理和控制,使得程序更加健壮和可靠,减少出错的可能性。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是使用Java JDBC封装数据库事务的代码示例: ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class TransactionExample { private static final String DB_URL = "jdbc:mysql://localhost:3306/mydatabase"; private static final String DB_USER = "root"; private static final String DB_PASSWORD = "password"; public static void main(String[] args) { Connection connection = null; Statement statement = null; try { // Establish database connection connection = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); // Turn off auto-commit mode connection.setAutoCommit(false); // Execute SQL statements within a transaction statement = connection.createStatement(); statement.executeUpdate("INSERT INTO users (username, password) VALUES ('user1', 'pass1')"); statement.executeUpdate("INSERT INTO users (username, password) VALUES ('user2', 'pass2')"); // Commit transaction connection.commit(); System.out.println("Transaction completed successfully."); } catch (SQLException e) { // Rollback transaction in case of errors try { if (connection != null) { connection.rollback(); System.out.println("Transaction rolled back."); } } catch (SQLException ex) { ex.printStackTrace(); } e.printStackTrace(); } finally { // Close resources try { if (statement != null) { statement.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { e.printStackTrace(); } } } } ``` 在上面的代码中,我们首先建立了一个数据库连接,然后通过调用 `setAutoCommit(false)` 方法来关闭自动提交模式,这样将使所有的 SQL 语句在一个事务中执行。接下来,我们执行了两个 SQL 语句来插入两条用户记录。如果这些语句都执行成功,我们将调用 `commit()` 方法来提交事务。如果在执行 SQL 语句时出现错误,我们将调用 `rollback()` 方法来回滚事务。最后,我们关闭了所有的数据库连接和语句对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值