新建PayMoneySvl
付款後清空购物车并更新帐户余额
为避免重复扣款,重定向到付款成功页面。
@WebServlet("/user/PayMoneySvl")
public class PayMoneySvl extends HttpServlet {
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//取得使用者
TUser user = (TUser)request.getSession().getAttribute("user");
//取得购买总额
String value = request.getParameter("allMoney");
double allMoney = Double.parseDouble(value);
//若余额足够
if(user.getAccount() >= allMoney){
//执行扣款及清理购物车
UserBiz biz = new UserBiz();
Map<String,Integer> car = (Map<String,Integer>)request.getSession().getAttribute("ShopCar");
try {
//处理订单,传入使用者名称、结帐总额、购物清单
biz.buyBooks(user.getUname(),allMoney,car);
//付款成功後清除购物车,并更新帐户余额
car.clear();
user.setAccount(user.getAccount() - allMoney);
//重定向至付款成功页面
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName()
+ ":" + request.getServerPort() + path + "/";
response.sendRedirect(basePath + "PayOkSvl?allMoney=" + allMoney);
}catch(Exception e) {
request.setAttribute("msg", "网路异常,请和管理员联系");
request.getRequestDispatcher("/error.jsp").forward(request, response);
}
}else {
request.setAttribute("msg", "余额不足");
request.getRequestDispatcher("/error.jsp").forward(request, response);
}
}
在UserBiz新增buyBooks()方法
public void buyBooks(String uname, double allMoney, Map<String, Integer> shopCar) {
IUserDao dao = new UserDaoMysql();
try {
//扣款时若其中一个动作失败,就全部回复。
dao.beginTransaction();
//因为是扣款,所以金额用负数
dao.updateUserAccount(uname,-allMoney);
dao.addBuyRecord(uname,allMoney,shopCar);
dao.commit();
}catch(Exception e) {
dao.rollback();
Log.logger.error(e.getMessage(),e);
throw e;
}finally {
dao.closeConnection();
}
}
在UserDaoMysql新增updateUserAccount()方法,实现扣款。
public void updateUserAccount(String uname,double money) throws Exception{
String sql = "update tuser set account = account + ? where uname = ?";
this.openConnection();
PreparedStatement ps = this.connection.prepareStatement(sql);
ps.setDouble(1, money);
ps.setString(2, uname);
ps.executeUpdate();
ps.close();
}
在UserDaoMysql新增addBuyRecord()方法,生成订单。
public void addBuyRecord(String uname,double allmoney,Map<String,Integer>ShopCar) throws Exception{
String orderNo = OrderUtil.createNewOrderNo();
String sql = "insert into tbuyrecord values(?,?,?,?)";
this.openConnection();
PreparedStatement ps = this.connection.prepareStatement(sql);
ps.setString(1, orderNo);
ps.setString(2, uname);
ps.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
ps.setDouble(4, allmoney);
ps.executeUpdate();
ps.close();
}
在UserDaoMysql新增addBuyDetail()方法,添加订单明细。
public void addBuyRecord(String uname,double allmoney,Map<String,Integer>shopCar) throws Exception{
//新增订单
String orderNo = OrderUtil.createNewOrderNo();
String sql = "insert into tbuyrecord values(?,?,?,?)";
this.openConnection();
PreparedStatement ps = this.connection.prepareStatement(sql);
ps.setString(1, orderNo);
ps.setString(2, uname);
ps.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
ps.setDouble(4, allmoney);
ps.executeUpdate();
//更新DB内商品资料
Set <String> isbns = shopCar.keySet();
for(String isbn:isbns) {
//把商品条码、购买数量、订单编号等资讯整理进TBuyDetail物件中。
TBuyDetail detail = new TBuyDetail();
detail.setIsbn(isbn);
detail.setBuycount(shopCar.get(isbn));
detail.setBuyid(orderNo);
//使用TBuyDetail物件对DB资料进行更新。
addBuyDetail(detail);
}
ps.close();
}
private void addBuyDetail(TBuyDetail detail) throws Exception{
//取得tbuydetail表取得autoId,再加入其他参数(商品号、订单号、数量)塞回去。
String sql = "insert into tbuydetail values((select * from (select IFNULL(max(autoid),0) + 1 from tbuydetail) t1),?,?,?)";
this.openConnection();
PreparedStatement ps = this.connection.prepareStatement(sql);
ps.setString(1, detail.getIsbn());
ps.setString(2, detail.getBuyid());
ps.setInt(3, detail.getBuycount());
ps.executeUpdate();
ps.close();
//用BookDao.updateBookCount()扣除库存
//为了能够完整进行transaction,把同一个connection丢给BookDao继续使用
BookDaoMysql bookDao = new BookDaoMysql();
bookDao.setConnection(this.getConnection());
bookDao.updateBookCount(detail.getIsbn(),-detail.getBuycount());
}
public void updateBookCount(String isbn, int bookCount) throws Exception{
String sql = "update tbook set bkcount = bkcount + ? where isbn = ?";
this.openConnection();
PreparedStatement ps = this.connection.prepareStatement(sql);
ps.setInt(1, bookCount);
ps.setString(1, isbn);
ps.executeUpdate();
ps.close();
}
从页面取得: 使用者名称、结帐金额、购物车,传给後台: PayMoneySvl
呼叫biz.buyBooks()执行transaction任务
1.执行扣款
2.使用addBuyRecord()新增订单,并更新库存
2-1使用userDao将资料分别填入订单表及订单细目表
订单表(订单号、客户名、时间、总额)
订单细目表(autoId、商品号、订单号、数量)
2-2
使用bookDao.updateBookCount()更新库存。与userDao使用同一个connection。
3.commit()
新建PayOkSvl,处理付款成功後的重定向
@WebServlet("/PayOkSvl")
public class PayOkSvl extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/main/PayOk.jsp").forward(request, response);
}
}
新建PayOk.jsp,显示付款成功讯息。
<table align="center" width=60%>
<tr>
<td height="180"></td>
<td style="color:black;font-size:18px">
付款成功!付款人:${user.uname }<br>
付款金额:<fmt:formatNumber value="${allMoney }" pattern="#.00" type="number"></fmt:formatNumber>
<p style="color:red;font-size:30px">我们会尽快为您寄送商品</p>
</td>
</tr>
<tr><td height="80"></td></tr>
<tr>
<td colspan="2" align="center">
<a href="<%=basePath%>MainSvl">返回首页</a>
</td>
</tr>
</table>
在transaction任务内的任何一步骤添加throw new RuntimeException("异常测试");
即可在DB进行数据确认,以及在console进行log确认
<<: 有关Wscript.exe *.vbs 的中文字编码( utf-8)问题
>>: CodeWars : 新手村练等纪录03- Stop gninnipS My sdroW!
MiniMap制作Part2 找到了tile生成时位置错乱的原因,还是因为进位造成的问题。A★内部是...
昨天介绍了Node.js,今天我们就要来实际安装Node.js啦 首先当然是到官网去下载Node.j...
上一篇在创造新的资料库时,有提到PRIMARY KEY也就是主键限制!那麽此篇来继续介绍FOREIG...
建立 Thread 的成本远低於 Process 的成本,执行 Context switch 时的效...
昨天了解了 Composite 是什麽後,一如我们本来的安排,今天要来介绍的是 Composites...