**
* 账户实体类:封装账户信息的
*/
public class Account { // 这种简单的对象被称为pojo对象。
// 一般属性不建议设计为基本数据类型,使用包装类,防止空带来的问题
/**
* 主键
*/
private Long id;
/**
* 账号
*/
private String actno;
/**
* 余额
*/
private Double balance;
public Account() {
}
public Account(Long id, String actno, Double balance) {
this.id = id;
this.actno = actno;
this.balance = balance;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getActno() {
return actno;
}
public void setActno(String actno) {
this.actno = actno;
}
public Double getBalance() {
return balance;
}
public void setBalance(Double balance) {
this.balance = balance;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", actno='" + actno + '\'' +
", balance=" + balance +
'}';
}
}
public class AccountDao {
/**
* 负责插入数据
*
* @param act 账户信息
* @return 1 表示插入成功
*/
public int insert(Account act) {
Connection conn = null;
PreparedStatement ps = null;
int count = 0;
try {
conn = DBUtil.getConnection();
String sql = "insert into t_act(actno,balance) values(?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, act.getActno());
ps.setDouble(2, act.getBalance());
count = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(null, ps, null);
}
return count;
}
/**
* 根据主键删除账户
*
* @param id
* @return
*/
public int deleteByID(Long id) {
Connection conn = null;
PreparedStatement ps = null;
int count = 0;
try {
conn = DBUtil.getConnection();
String sql = "delete from t_act where id=?";
ps = conn.prepareStatement(sql);
ps.setLong(1, id);
count = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(null, ps, null);
}
return count;
}
/**
* 更改账户信息
*
* @param act 账户
* @return
*/
public int update(Account act) {
Connection conn = null;
PreparedStatement ps = null;
int count = 0;
try {
conn = DBUtil.getConnection();
String sql = "update t_act set actno=?,balance=? where id=?";
ps = conn.prepareStatement(sql);
ps.setString(1, act.getActno());
ps.setDouble(2, act.getBalance());
ps.setLong(3, act.getId());
count = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(null, ps, null);
}
return count;
}
/**
* 根据账号查询账户信息
*
* @param actno
* @return
*/
public Account selectByActno(String actno) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
Account act = null;
try {
conn = DBUtil.getConnection();
String sql = "select actno,balance from t_act where actno=?";
ps = conn.prepareStatement(sql);
ps.setString(1, actno);
rs = ps.executeQuery();
if (rs.next()) {
Long id = rs.getLong("id");
double balance = rs.getDouble("balance");
act = new Account();
act.setId(id);
act.setActno(actno);
act.setBalance(balance);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(null, ps, rs);
}
return act;
}
/**
* 查询所有用户信息
*
* @return
*/
public List<Account> selectAll() {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
List<Account> accountList = null;
try {
conn = DBUtil.getConnection();
String sql = "select id,actno,balance from t_act";
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next()) {
Long id = rs.getLong("id");
String actno = rs.getString("actno");
Double balance = rs.getDouble("balance");
Account act = new Account(id, actno, balance);
accountList.add(act);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(null, ps, rs);
}
return accountList;
}
}
/**
* 专门处理Account业务的一个类
* 在该类中编写纯业务代码
*/
public class AccountService {
// 这里的方法起名要表明处理什么业务
private AccountDao accountDao = new AccountDao();
/**
* 完成转账的业务逻辑
*
* @param fromActno 转出账户
* @param toAcrno 转入账户
* @param money 转账金额
*/
public void transfer(String fromActno, String toAcrno, double money) throws MoneyNotEnoughException, AppException {
// 查询余额是否充足
try (Connection connection = DBUtil.getConnection()){
// 开启事务
connection.setAutoCommit(false);
Account fromAccount = accountDao.selectByActno(fromActno);
Double fromAccountBalance = fromAccount.getBalance();
if (fromAccountBalance < money) {
throw new MoneyNotEnoughException("对不起,余额不足");
}
Account toAccount = accountDao.selectByActno(toAcrno);
Double toAccountBalance = toAccount.getBalance();
// 从转出账户中减去money
fromAccount.setBalance(fromAccountBalance - money);
int count = accountDao.update(fromAccount);
// 向转入账户中添加money
toAccount.setBalance(toAccountBalance + money);
count += accountDao.update(toAccount);
if (count!=2) {
throw new AppException("账户转账异常!");
}
// 提交事务
connection.commit();
} catch (SQLException e) {
throw new AppException("账户转账异常!");
}
}
}
工作过程:当用户发送过来一个请求,首先会在Controller层进行处理,当用户发送转账需求的时候,Controller层首先会进行处理,并调用Model层相应的业务方法(transfer),在Model层执行transfer的时候,会自动创建AccounDao对象执行相应的操作,最终将结果返给Controller,然后Controller层根据Model层里面传来的结果,调用View层进行展示。
/**
* 账户小程序
* AccountServlet是一个Controller
*
* @author 琨哥
* @version 2.0
* @since 2.0
*/
@WebServlet("/transfer")
public class AccountServlet extends HttpServlet {
private AccountService actService = new AccountService();
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 接收数据,调用业务方法(Model)处理业务
String fromActno = request.getParameter("fromActno");
String toActno = request.getParameter("toActno");
double money = Double.parseDouble(request.getParameter("money"));
try {
actService.transfer(fromActno, toActno, money);
// 执行到这里说明转账成功,调用view层展示响应的代码
response.sendRedirect(request.getContextPath()+"/success.jsp");
} catch (MoneyNotEnoughException e) {
// 调用view层进行展示
response.sendRedirect(request.getContextPath() + "/MoneyNotEnough.jsp");
} catch (Exception e) {
response.sendRedirect(request.getContextPath() + "/error.jsp");
}
}
}
这样Controller负责业务的调度和页面的展示,Model层负责编写业务逻辑,view层负责编写前端页面,分工合作极大的提高了代码的复用性!