Forder (訂單主表) + Sorder (訂單項) 同步入庫,外鍵自動維護。
@Entity
public class Forder implements Serializable {
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "forder")
public List getSorders() { return sorders; }
// setter 省略
}
@Entity
public class Sorder implements Serializable {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "fid")
public Forder getForder() { return forder; }
// setter 省略
}
關鍵點:cascade = ALL + mappedBy 指定關係維護端。保存 Forder 時自動 persist 所有關聯 Sorder 並填充外鍵 fid。
@Service("sorderService")
public class SorderServiceImpl extends BaseServiceImpl implements SorderService {
@Override
public Forder addSorder(Forder forder, Product product) {
Sorder sorder = productToSorder(product);
// 合併同款商品
for (Sorder old : forder.getSorders()) {
if (old.getProduct().getId().equals(sorder.getProduct().getId())) {
old.setNumber(old.getNumber() + sorder.getNumber());
return forder;
}
}
// 新商品:雙向綁定關係
sorder.setForder(forder); // 關鍵!
forder.getSorders().add(sorder); // 關鍵!
return forder;
}
// productToSorder 省略
}
@Controller("forderAction")
@Scope("prototype")
public class ForderAction extends BaseAction {
@Override
public Forder getModel() {
return (Forder) session.get("forder"); // 直接返回 Session 中的訂單模型
}
public String save() {
model.setUser((User) session.get("user"));
model.setStatus(new Status(1)); // 待付款
forderService.save(model); // 級聯持久化
// 雙重緩存解決:保留舊訂單供支付頁用,Session 放入新空訂單
session.put("oldForder", session.get("forder"));
session.put("forder", new Forder()); // 清空購物車
return "bank"; // 跳轉支付頁
}
}
<% response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); %>
<% response.setHeader("Pragma", "no-cache"); %>
<% response.setDateHeader("Expires", 0); %>
確認訂單後,Session 中 forder 被替換為**新空對象**。用戶點「返回」→ 重新請求確認頁 → Action getModel() 返回新空訂單 → 判斷為空 → 重定向首頁。
// 確認訂單頁 JSP 片段
| 層面 | 方案 | 作用 | 局限 |
|---|---|---|---|
| 客戶端 | HTTP 頭禁用緩存 | 阻止瀏覽器緩存頁面 | 刷新/強制載入仍可見舊內容 |
| 服務端 | Session 數據失效 (替換為空對象) | 從數據源頭切斷舊訂單 | 需配合客戶端邏輯判斷 |
| 綜合 | 雙重保險 | 徹底杜絕重複提交 | 最佳實踐 |
電商訂單系統「冪等性」設計精髓:**業務狀態機 + Session 狀態同步**。確認訂單瞬間完成「購物車 → 訂單」狀態遷移,Session 即時反映新狀態,瀏覽器緩存變得無害。這比單純依賴 Token 或 HTTP 頭更可靠、更符合業務直覺。