记账本开发记录——第十八天(2020.2.5)

今天学习了一个名为事务的东西。这个东西对于我是陌生的。事务,即主要用于处理一些操作量大,复杂度高的操作。在上学期的一系列学习中,由于系主任只是简单粗暴的想让我们学会增删改查,这种涉及工程的东西也难怪我们没有接触。但说到底还是要做工程的。今天对于事务进行了一个基本的了解。

首先,什么是事务,按照官方理解 就是一件事情有n个组成单元 要不这n个组成单元同时成功 要不n个单元就同时失败,就是将n个组成单元放到一个事务中。其实照自己的理解来说,就是将多个操作捆绑到一起,要成功就一起成功,要失败就一起失败。说到底是为了防止一些意外发生,比如一个转账操作,如果在执行完转出后发生了异常,转入操作无法执行了,那这个客户的钱不就没了?这上哪说理去。事物就是为了防止这种情况的发生。我们一般使用的数据库是mysql,mysql的事务如下:

默认的事务:一条sql语句就是一个事务 默认就开启事务并提交事务

手动事务:

1)显示的开启一个事务:start transaction

2)事务提交:commit代表从开启事务到事务提交 中间的所有的sql都认为有效 真正的更新数据库

3)事务的回滚:rollback 代表事务的回滚 从开启事务到事务回滚 中间的所有的 sql操作都认为无效数据库没有被更新

在了解了这个基础上,我们可以分别使用JDBC和DBUtils做个demo来测试。

 1 package jdbc;
 2 
 3 import java.sql.Connection;
 4 import java.sql.DriverManager;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7 
 8 import com.mysql.cj.jdbc.Driver;
 9 
10 public class JDBCDemo {
11     public static void main(String[] args) throws SQLException  {
12         
13         //通过jdbc去控制事物
14         Connection conn = DriverManager.getConnection("jdbc:mysql:////day19", "root", "abc456");
15         //1.注册驱动
16         try {
17             Class.forName("com.mysql.jdbc.Driver");
18             //2.获得connection
19             
20             //手动开启事务
21             conn.setAutoCommit(false);
22             
23             
24             //3.获得执行平台
25             Statement stmt = conn.createStatement();
26             
27             //4.操作sql
28             stmt.executeUpdate("insert into account values(null,'jackson',3000)");
29             
30             //提交事务
31             conn.commit();
32             
33             stmt.close();
34             conn.close();
35         } catch (Exception e) {
36             e.printStackTrace();
37             conn.rollback();
38         }
39 
40     }
41     
42 }
JDBCDemo
 1 package utils;
 2 
 3 import java.sql.Connection;
 4 import java.sql.SQLException;
 5 
 6 import org.apache.commons.dbutils.QueryRunner;
 7 
 8 public class DBUtilsDemo {
 9     public static void main(String[] args) throws SQLException {
10         
11         Connection conn = DataSourceUtils.getConnection();
12         try {
13             QueryRunner runner = new  QueryRunner();
14             //开启事务
15             
16             //runner.update("update account set money=10000 where name = 'tom'");
17             //获得一个connection
18 
19             runner.update(conn, "update account set money=10000 where name = 'tom'");
20             conn.setAutoCommit(false);
21             //提交或回滚事务
22             conn.commit();
23         } catch (SQLException e) {
24             conn.rollback();
25             // TODO Auto-generated catch block
26             e.printStackTrace();
27         }
28         
29     }
30 
31 }
DBUtilsDemo

通过这个demo更好的了解事务后,就可以做一个关于转账的基本操作了:

页面是这个样子的:

 页面代码就不贴了。

web层:

package transfer.web;

import java.io.IOException;
import java.sql.SQLException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import transfer.service.TransferService;

/**
 * Servlet implementation class TransferServlet
 */
@WebServlet("/Transfer")
public class TransferServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public TransferServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        //接收转账参数
        String out = request.getParameter("out");
        String in = request.getParameter("in");
        String moneyStr = request.getParameter("money");
        double money = Double.parseDouble(moneyStr);
        
        //调用业务层的转账方法
        TransferService service = new TransferService();
        boolean isTransferSuceess;
        try {
            isTransferSuceess = service.transfer(out,in,money);
            if(isTransferSuceess) {
                response.getWriter().write("转账成功");
            }else {
                response.getWriter().write("转账失败");
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doGet(request, response);
    }

}

 service层:

package transfer.service;

import java.sql.Connection;
import java.sql.SQLException;

import transfer.dao.TransferDao;
import utils.DataSourceUtils;

public class TransferService {

    public boolean transfer(String out, String in, double money) throws SQLException {
        Connection conn = DataSourceUtils.getConnection();
        //创建dao对象
        TransferDao dao = new TransferDao();
        boolean isTransferSuccess = true;
        try {
            //开启事务
            conn.setAutoCommit(false);
            dao.out(conn,out,money);
            int i=1/0;
            dao.in(conn,in,money);
        } catch (Exception e) {
            isTransferSuccess = false;
            //回滚事务
            conn.rollback();
            e.printStackTrace();
        }finally {
            conn.commit();
        }
        
        return isTransferSuccess;
    }

}

dao层:

package transfer.dao;

import java.sql.Connection;
import java.sql.SQLException;

import org.apache.commons.dbutils.QueryRunner;

import utils.DataSourceUtils;

public class TransferDao {

    public void out(Connection conn,String out, double money) throws SQLException {
        QueryRunner runner = new QueryRunner();
        //Connection conn = DataSourceUtils.getConnection();
        String sql = "update account set money = money-? where name=?";
        runner.update(conn,sql,money,out);
        
    }

    public void in(Connection conn,String in, double money) throws SQLException {
        QueryRunner runner = new QueryRunner();
        //Connection conn = DataSourceUtils.getConnection();
        String sql = "update account set money = money+? where name=?";
        runner.update(conn,sql,money,in);
        
    }

}

需要注意的是,我们对于事务的处理一般位于service层,在其中添加事务的基本操作。

(关于事务的内容还有很多,但碍于进度问题,这里暂时搁置)

明日:复习增删改查,后天使用DBUtils,数据库连接池,BeanUtils进行记账本的增删改查,将页面改写为jsp,将导航栏部分做成固定jsp等等。

原文地址:https://www.cnblogs.com/wushenjiang/p/12266117.html