Service层控制事务

1.Service业务逻辑层:


1.业务概述:
代表用户完成的一个业务功能,可以由一个或多个DAO的调用组成。(软件所提供的一个功能都叫业务)


2.Service开发流程
在这里插入图片描述

2.事务:


在JDBC中,在Service层实现事务需要以下几个步骤:
获得Connection对象开始事务–提交或回滚–关闭连接。其事务策略是

  1. 获得Connection对象开始事务:
    connection.setAutoCommit(false);//true等价于1,false等价于0,将自动提交事务改为手动提交事务
  2. 提交或回滚
    connection.commit();//手动提交事务
    connection.rollback();//手动回滚事务
  3. 关闭连接
    connection.close()

3.问题:


对于Service层获得的数据库连接,其与DAO层所获得的数据库连接直接操作数据库的连接并不相同,所以Service层数据库连接提交或回滚并不影响DAO层的数据库连接!!!

4.问题解决办法:


1.解决方案1:传递Connection
为了解决线程中Connection对象不同步的问题,可以将Connection对象通过service传递给各个DAO方法,实现Service层数据库连接与DAO层数据库连接相同,实现事务的回滚与提交
|
传递Connection出现的问题:

  • 如果使用传递Connection,容易造成接口污染(不同的数据库厂商和框架的数据库连接不同,不一定是Connection)。
  • 定义接口是为了更容易更换实现,从而实现面向接口编程,而将Connection定义在接口中,会造成污染当前接口。

2.解决方案2:ThreadLocal

  • 可以将整个线程中(单线程)中,存储一个共享值。
  • 线程拥有一个类似Map的属性,键值对结构<ThreadLocal对象,值>。
  • 一个线程共享同一个ThreadLocal,在整个流程中任一环节可以存值或取值。
  • 当在线程中存储connection连接时,Service与DAO用的connection连接相同,所以在DAO层用完connection后不要关闭,最后在Service层关闭connection

完善!!!:
为保证程序各层各司其职,Service层不应该出现connection连接对象,更不应该释放资源,所以将代码封装在DBUtils中!!!!

5.示例代码:

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class DBUtils {
    private static final Properties PROPERTIES=new Properties();    //存储配置文件的map



    //Driver只加载一次,避免调用getConnection()方法时,检查Driver类是否已加载到程序中!
    static {
        InputStream is= DBUtils.class.getResourceAsStream("/db.properties");//通过复用文本自带流,读取配置文件
        try {
            PROPERTIES.load(is);    //通过properties对象,将流中配置信息分成键值对
            String driverName=PROPERTIES.getProperty("driver"); //通过键获取值
            Class.forName(driverName);  //加载驱动类
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //创建一个线程,达到一个程序共享连接
    private static ThreadLocal<Connection> threadLocal=new ThreadLocal<>();

    //1.获取连接
    public static Connection getConnection(){
        //将当前线程中绑定的connection对象,赋值给connection
        Connection connection=threadLocal.get();

        try {
            if(connection==null){
                String url=PROPERTIES.getProperty("url");
                String username=PROPERTIES.getProperty("username");
                String password=PROPERTIES.getProperty("password");
                connection= DriverManager.getConnection(url,username,password);
                //把连接存在当前共享的线程中
                threadLocal.set(connection);
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    //开启事务
    public  static void begin(){
        Connection connection=getConnection();
        try {
            connection.setAutoCommit(false);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    //提交事务
    public static void commit(){
        //所有连接都是通过ThreadLocal获得,连接是同一个连接
        Connection connection=null; //  防止在此处出现异常
        try {
            connection=getConnection();
            connection.commit();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //提交事务后应该释放资源
            closeAll(connection,null,null);
        }
    }

    //回滚事务、
    public static void rollback(){
        Connection connection=null;
        try {
            connection=getConnection();
            connection.rollback();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            closeAll(connection,null,null);
        }
    }

    //2.释放资源
    public static void closeAll(Connection connection, Statement statement, ResultSet resultSet){
        try {
            if(resultSet!=null){
                resultSet.close();
            }
            if(statement!=null){
                statement.close();
            }
            if(connection!=null){
                connection.close();
                threadLocal.remove();   //  关闭连接后,移除已关闭的connection对象!!!
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值