課程回顧
1. FastJson工具類的使用(把對象轉換成json的字符串)
* 先導入開發的jar包
* 基本的操作:使用JSON.toJsonString(object)
* 採用引用的方式,禁止死循環的問題。禁止引用的方式,引發死循環的問題。
2. Struts2框架配置全局異常處理
* dao和service層出現了異常,會默認拋出異常。在Action有2種選擇
* 拋出
* 捕獲異常,自定義異常的信息。
3. 郵件的開發
* JavaMail的方式
* Spring整合JavaMail(推薦的方式)
購銷合同模塊
購銷合同的概述
1. 什麼是購銷合同
* 公司銷售和海外客戶簽訂訂單(合同),客戶訂單中包含貨物,公司聯繫生產廠家生產貨物,和生成廠家簽訂的合同稱爲購銷合同。
2. 購銷合同的組成,主要由三部分組成(推薦查看購銷合同的excel,查看購銷合同的屬性信息)
* 購銷合同的主信息
* 多個貨物的信息
* 多個附件的信息
* 注意1:購銷合同最多隻包含兩款商品,如果包含多個商品,一張A4紙打印放不下。
* 注意2:一個A4紙上存放2個產品,要求該產品需要是一個廠家生產的。
3. 通過查看購銷合同的excel文檔,簡單的瞭解購銷合同信息的組成
* 下面需要考慮的是購銷合同相關的表結構的設計
數據庫表結構設計的三大範式
1. 第一範式:做到每一列不可拆分
* 每一列的原子性
2. 第二範式:確保一張表只做一件事情
* 例如:用戶張三,年齡是20,性別是男,WEB考試成績是90分,Maven考試成績是95分,Oracle考試成績是100分。
* 這種表結構的設計就是用戶一張表,又描述了學生的信息,又描述了成績的信息。
3. 第三範式:在滿足第二範式的同時,消除表中的傳遞依賴,目標是空間最省。
* 例如:3<4 4<5 所以3<5 根據依賴傳遞
* 例如:設計一張表,商品的主鍵、商品的名稱、商品的單價、商品的數量、商品的總價格。
4. 反第三範式
* 在進行數據庫設計的時候,首選確保你所設計的表結構都能達到第三範式的要求
* 但是在實際開發中,爲了滿足一些用戶的特殊需求,開發時又會在符合第三範式的表中,添加冗餘字段,結果導致不符合了第三範式,一般稱爲反三範式。
購銷合同數據庫的設計
1. 購銷合同的暫時組成
* 購銷合同表
* 貨物表
* 附件表
* 生產廠家表
分散設計思想
1. 問題
* 在查詢購銷合同的總金額時,需要關聯加載購銷合同下的所有貨物,並且加載貨物下的所有附件,這樣顯示購銷合同的金額時,查詢會消耗大量的時間,查詢速度比較慢
2. 解決,採用分散設計思想
* 在平時添加貨物時,添加附件時,分別計算出貨物的總金額、附件的總金額,再更新購銷合同的金額。
* 這樣就相當於將一次集中計算的工作量分散到多次計算過程中,再查詢購銷合同的速度就比較快速。
3. 優缺點
* 缺點是代碼的編寫量和維護工作量會提升。
* 優點是提供頁面數據的檢索速度。
編寫程序代碼
編寫domain和映射的配置文件
1. 導入資料中的JavaBean
編寫service和實現類
1. 導入service的接口和實現類
購銷合同的CRUD的操作
1. 強調:購銷合同的模塊的名稱是cargo
* 創建cn.itcast.jk.action.cargo包結構
* 在struts文件夾下創建struts-cargo.xml配置文件(在struts.xml配置文件引入該配置文件)
<!-- 包名,強調:名稱空間必須是cargo,因爲數據庫中菜單的訪問路徑已經是固定的了 -->
<package name="cargo" namespace="/cargo" extends="default">
<action name="contractAction_*" class="contractAction" method="{1}">
<result name="list">/WEB-INF/pages/cargo/contract/jContractList.jsp</result>
<result name="toview">/WEB-INF/pages/cargo/contract/jContractView.jsp</result>
<result name="tocreate">/WEB-INF/pages/cargo/contract/jContractCreate.jsp</result>
<result name="page" type="redirectAction">contractAction_list</result>
<result name="toUpdate">/WEB-INF/pages/cargo/contract/jContractUpdate.jsp</result>
</action>
</package>
2. 完成CRUD的操作
* 購銷合同的新增的時候,兩點注意
* 新增購銷合同,默認的狀態是0 0表示草稿 1表示已經上報
* 新增購銷合同,默認的總金額是0元,設置0d
3. 修改購銷合同通過的功能
public String update() throws Exception {
// 從數據庫中查詢出來
Contract contract = contractService.get(Contract.class, model.getId());
contract.setCustomName(model.getCustomName());
contract.setPrintStyle(model.getPrintStyle());
contract.setContractNo(model.getContractNo());
contract.setOfferor(model.getOfferor());
contract.setInputBy(model.getInputBy());
contract.setCheckBy(model.getCheckBy());
contract.setInspector(model.getInspector());
contract.setSigningDate(model.getSigningDate());
contract.setImportNum(model.getImportNum());
contract.setShipTime(model.getShipTime());
contract.setTradeTerms(model.getTradeTerms());
contract.setDeliveryPeriod(model.getDeliveryPeriod());
contract.setCrequest(model.getCrequest());
contract.setRemark(model.getRemark());
// 更新購銷合同
contractService.saveOrUpdate(contract);
return SUCCESS;
}
4. 提交和取消購銷合同的功能
* 提交:把購銷合同的狀態從草稿變成已上報。(state從0修改成1)
* 取消:把購銷合同的狀態從已上報變成操作。(state從1修改成0)
貨物和附件模塊
貨物模塊
1. 構建ContractProductAction,完成相關編寫和配置。
2. 貨物的分頁功能
* 點擊購銷合同列表頁面的貨物按鈕,跳轉到貨物的新增頁面,但是新增頁面的下方需要顯示該購銷合同已經存在的貨物列表數據。
* 解決思路
* 需要工廠的數據列表(注意:工廠是分成貨物工廠和附件工廠的,狀態爲1表示和咱們公司有合作關係的)
* 需要查詢該購銷合同下所有的貨物信息數據
* 具體的代碼如下
/**
* 跳轉到添加部門頁面
* @return
* @throws Exception
*/
public String tocreate() throws Exception {
// 查詢工廠信息
List<Factory> factoryList = factoryService.find("from Factory where ctype = '貨物' and state = 1", Factory.class,
null);
super.put("factoryList", factoryList);
// 傳遞的是購銷合同的主鍵
// 查詢的是該購銷合同下所有的貨物數據
page = contractProductService.findPage("from ContractProduct where contract.id = ?", page, ContractProduct.class,
new String[] { model.getContract().getId() });
// 設置url
page.setUrl("contractProductAction_tocreate");
super.push(page);
return "tocreate";
}
3. 貨物的新增功能
* 計算這一次的獲取的總金額
* 獲取到購銷合同中的總金額,購銷合同總金額 = 總金額 + 貨物的總金額
* 更新購銷合同數據
* 業務層代碼如下
public void saveOrUpdate(ContractProduct entity) {
// 判斷,如果是新增,設置部門的狀態爲1
if(UtilFuns.isEmpty(entity.getId())){
// 添加變量,表示購銷合同總金額
double money = 0.0;
// 如果貨物的數量不爲空,並且貨物的單價不爲空
if(UtilFuns.isNotEmpty(entity.getCnumber()) && UtilFuns.isNotEmpty(entity.getPrice())){
// 計算貨物的總金額
money = entity.getCnumber() * entity.getPrice();
// 設置貨物的總金額
entity.setAmount(money);
// 獲取到購銷合同的總金額
String id = entity.getContract().getId();
Contract contract = baseDao.get(Contract.class, id);
// 設置購銷合同的總金額
contract.setTotalAmount(contract.getTotalAmount()+money);
// 更新購銷合同
baseDao.saveOrUpdate(contract);
}
}
baseDao.saveOrUpdate(entity);
}
2. 貨物的修改功能
* 如果修改了貨物的數量或者單價,那麼也要更新購銷合同的總金額
* 減去原來的金額,加上修改後的金額
* 業務層代碼如下
public void saveOrUpdate(ContractProduct entity) {
// 判斷,如果是新增,設置部門的狀態爲1
if(UtilFuns.isEmpty(entity.getId())){
// 添加變量,表示購銷合同總金額
double money = 0.0;
// 如果貨物的數量不爲空,並且貨物的單價不爲空
if(UtilFuns.isNotEmpty(entity.getCnumber()) && UtilFuns.isNotEmpty(entity.getPrice())){
// 計算貨物的總金額
money = entity.getCnumber() * entity.getPrice();
// 設置貨物的總金額
entity.setAmount(money);
// 獲取到購銷合同的總金額
String id = entity.getContract().getId();
Contract contract = baseDao.get(Contract.class, id);
// 設置購銷合同的總金額
contract.setTotalAmount(contract.getTotalAmount()+money);
// 更新購銷合同
baseDao.saveOrUpdate(contract);
}
}else{
// 先獲取到原有的貨物的總金額
double amount = entity.getAmount();
// 設置新的金額
double money = 0.0;
// 如果貨物的數量不爲空,並且貨物的單價不爲空
if(UtilFuns.isNotEmpty(entity.getCnumber()) && UtilFuns.isNotEmpty(entity.getPrice())){
// 計算貨物的總金額
money = entity.getCnumber() * entity.getPrice();
// 設置貨物的總金額
entity.setAmount(money);
// 獲取到購銷合同的總金額
String id = entity.getContract().getId();
Contract contract = baseDao.get(Contract.class, id);
// 設置購銷合同的總金額,更新 = 減去原有的購銷合同金額 + 新改變的購銷合同金額
contract.setTotalAmount(contract.getTotalAmount() - amount + money);
// 更新購銷合同
baseDao.saveOrUpdate(contract);
}
}
baseDao.saveOrUpdate(entity);
}
3. 貨物的刪除功能
* 加載貨物對象
* 通過獲取對象獲取到所有的附件對象
* 加載購銷合同對象
* 遍歷附件對象,購銷合同一個一個刪除附件總金額
* 購銷合同刪除貨物金額
* 更新購銷合同金額
* 刪除貨物對象(默認配置了級聯刪除)
* 刪除的業務層代碼
public void deleteById(Class<ContractProduct> entityClass, Serializable id) {
// 刪除貨物對象
// 獲取到貨物對象
ContractProduct product = baseDao.get(ContractProduct.class, id);
// 獲取到該貨物下所有的附件對象
Set<ExtCproduct> extCproducts = product.getExtCproducts();
// 加載購銷合同對象
Contract contract = product.getContract();
// 先刪除附件的總金額
for (ExtCproduct extCproduct : extCproducts) {
// 遍歷一次,減去附件的金額,重新給購銷合同設置
contract.setTotalAmount(contract.getTotalAmount() - extCproduct.getAmount());
}
// 刪除貨物的金額
contract.setTotalAmount(contract.getTotalAmount() - product.getAmount());
// 更新購銷合同的金額
baseDao.saveOrUpdate(contract);
baseDao.deleteById(entityClass, id);
}