记账本开发记录——第十八天(2020.2.5)
分类:
IT文章
•
2025-02-04 17:25:43
今天学习了一个名为事务的东西。这个东西对于我是陌生的。事务,即主要用于处理一些操作量大,复杂度高的操作。在上学期的一系列学习中,由于系主任只是简单粗暴的想让我们学会增删改查,这种涉及工程的东西也难怪我们没有接触。但说到底还是要做工程的。今天对于事务进行了一个基本的了解。
首先,什么是事务,按照官方理解 就是一件事情有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等等。