工具类解决事务和过滤器解决事务

事务的四大特性ACID

原子性:强调事务的不可分割.多条语句要么都成功,要么都失败。
一致性:强调的是事务的执行的前后,数据要保持一致
隔离性:并发访问数据库时,一个事务的执行不应该受到其他事务的干扰.
持久性:一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

事务的隔离级别

READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读

READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读 仍有可能发生

REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修 改,可以阻止脏读和不可重复读,但幻读仍有可能发生。

SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务 之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
在这里插入图片描述

JdbcUtils 事务工具类

public class JdbcUtils {

    //准备Properties集合
    private static Properties config=new Properties();
    //连接池
    private static DataSource dataSource;

    //当前线程
    private static ThreadLocal<Connection> tl=new ThreadLocal<>();

    static {

        try {
            //1.读取properties文件的内容
            InputStream in = JdbcUtils.class.getClassLoader().
            getResourceAsStream("datasource.properties");

            config.load(in);

            //2.创建连接池
            DruidDataSource druidDataSource=new DruidDataSource();
            druidDataSource.setDriverClassName(config.getProperty("jdbc.driverClassName"));
            druidDataSource.setUrl(config.getProperty("jdbc.url"));
            druidDataSource.setUsername(config.getProperty("jdbc.username"));
            druidDataSource.setPassword(config.getProperty("jdbc.password"));

            dataSource=druidDataSource;

        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("创建数据库连接池失败!");
        }

    }

    /**
     * 获取链接
     * @return
     */
    public static Connection getConnection(){
        try {

            //1.先从当前线程获取链接
            Connection connection = tl.get();

            //2.如果当前线程连接为空,代表第一次调用
            if(connection==null){

                //2.1获取一个新的连接
                connection=dataSource.getConnection();

                //2.2 绑定连接到当前线程
                tl.set(connection);

            }

            return connection;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("获取连接失败!");
        }
    }

    /**
     * 开启事务
     */
    public static void startTransaction(){

        try {
            //1.获取链接
            Connection connection = getConnection();

            //2.开启事务
            connection.setAutoCommit(false);
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("开启事务");
        }

    }


    /**
     * 提交事务
     */
    public static void commitTransaction(){

        try {
            //1.获取链接
            Connection connection = tl.get();

            //2.如果当前线程有连接才提交事务
            if (connection != null) {
                connection.commit();
            }

        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("提交事务失败!");
        }

    }

    /**
     * 回滚事务
     */
    public static void rollback(){

        try {
            //1.获取链接
            Connection connection = tl.get();

            //2.如果当前线程有连接才回滚
            if (connection != null) {
                connection.rollback();
                connection.commit();
            }

        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("回滚事务失败!");
        }

    }

    /**
     * 关闭链接,移除当前线程绑定的连接
     */
    public static void closeTransaction(){

        try {
            //1.获取链接
            Connection connection = tl.get();

            if (connection != null) {
                //移除当前线程绑定的连接
                tl.remove();
                //关闭链接
                connection.close();
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("关闭链接失败!");
        }
        
    }



    /**
     * 关闭资源
     * @param st
     * @param rs
     */
    public static void close(Statement st, ResultSet rs){

        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs=null;
        }


        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            st=null;
        }




    }

}

dao

public interface AccountDao {

    /**
     * 根据id查询账户信息
     * @param id
     * @return
     */
    Account findAccountById(Integer id);

    /**
     * 修改账户信息
     * @param account
     */
    void updateAccount(Account account);

}
public class AccountDaoImpl implements AccountDao {


    @Override
    public Account findAccountById(Integer id) {

        PreparedStatement st=null;
        ResultSet rs=null;
        try{

            Connection conn=JdbcUtils.getConnection();

            //3.准备sql
            String sql="select id,name,money from account where id=?";

            st=conn.prepareStatement(sql);

            //4.设置参数
            st.setInt(1,id);

            //5.执行sql
            rs=st.executeQuery();

            //6.解析结果

            Account account=null;

            if(rs.next()){
                account=new Account();
                account.setId(id);
                account.setName(rs.getString("name"));
                account.setMoney(rs.getDouble("money"));
            }


            return account;
        }catch (Exception e){
            e.printStackTrace();
            throw new RuntimeException("查询失败!");
        }finally {
            JdbcUtils.close(st,rs);
        }
    }

    @Override
    public void updateAccount(Account account) {
        PreparedStatement st=null;
        ResultSet rs=null;
        try{

            Connection conn=JdbcUtils.getConnection();

            //3.准备sql
            String sql="update account set money=?,name=? where id=?";

            st=conn.prepareStatement(sql);

            //4.设置参数
            st.setDouble(1,account.getMoney());
            st.setString(2,account.getName());
            st.setInt(3,account.getId());

            //5.执行sql
            st.executeUpdate();


        }catch (Exception e){
            e.printStackTrace();

            throw new RuntimeException("修改失败!");
        }finally {
            JdbcUtils.close(st,rs);
        }
    }
}

service

public class AccountServiceImpl implements AccountService {

    private AccountDao accountDao=new AccountDaoImpl();

    @Override
    public void transfer(Integer sourceId, Integer targetId, Double money) {
        

            //1.查询源账户信息
            Account sAccount = accountDao.findAccountById(sourceId);

            //2.查询目标账户信息
            Account tAccount = accountDao.findAccountById(targetId);

            //3.转账的业务
            if (sAccount.getMoney() < money) {
                throw new RuntimeException("余额不足!");
            }

            //4.源账户扣钱
            sAccount.setMoney(sAccount.getMoney() - money);
            accountDao.updateAccount(sAccount);

            //int x = 1 / 0;

            //5.目标账户加钱
            tAccount.setMoney(tAccount.getMoney() + money);
            accountDao.updateAccount(tAccount);

            
    }


}

servlet

@WebServlet("/accountServlet")
public class AccountServlet extends HttpServlet {


    private AccountService accountService=new AccountServiceImpl();

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        try {
            //1.开启事务
            JdbcUtils.startTransaction();

            //2.执行业务
            AccountService accountService = new AccountServiceImpl();

            accountService.transfer(1, 2, 3.0);

            //3.提交事务
            JdbcUtils.commitTransaction();

        }catch (Exception e){
            e.printStackTrace();
            //回滚事务
            JdbcUtils.rollback();
        }finally {
            //关闭资源,移除当前线程绑定的连接
            JdbcUtils.closeTransaction();
        }



    }
}

过滤器解决事务

@WebFilter("/*")
public class TransactionFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        try{

            //1.开启事务
            JdbcUtils.startTransaction();


            //2.执行业务  放行
            chain.doFilter(req,res);


            //3.提交事务
            JdbcUtils.commitTransaction();

        }catch (Exception e){
            e.printStackTrace();
            //回滚事务
            JdbcUtils.rollback();
        }finally {
           //关闭资源,移除当前线程绑定的连接
            JdbcUtils.closeTransaction();
        }

    }

    @Override
    public void destroy() {

    }
}
  • 10
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值