サンプルプロジェクトはこちら S2DAOExam.zip
(ビルドや実行には Eclipse + m2plugin が必要です)
DAO層 | Data Base の1テーブルに対する CRUD (Create, Read, Update, Delete) 操作を行う |
Model層 | アプリケーションが扱う業務データと業務知識(与信枠の計算方法など)を実現する層。複数のDAOを使う。 |
Service層 | ひとまとまりの業務処理を実現する層。複数の Model を使う。トランザクションの単位となる |
Client層 | WebサービスやWebアプリなどのユーザインタフェース層 |
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN" "http://www.seasar.org/dtd/components.dtd"> <components> <include path="dao.dicon"/> <!-- DAOs --> <component name="CustomerDao" class="com.snail.exam.s2dao.CustomerDao"> <aspect>dao.interceptor</aspect> </component> <component name="OrderDao" class="com.snail.exam.s2dao.OrderDao"> <aspect>dao.interceptor</aspect> </component> <component name="ItemDao" class="com.snail.exam.s2dao.ItemDao"> <aspect>dao.interceptor</aspect> </component> <!-- Models --> <component name="TradeModel" class="com.snail.exam.s2dao.TradeModel"> <aspect>j2ee.requiredTx</aspect> <arg>CustomerDao</arg> <arg>ItemDao</arg> <arg>OrderDao</arg> </component> <!-- Services --> <component name="TradeService" class="com.snail.exam.s2dao.TradeService"> <aspect>j2ee.requiresNewTx</aspect> <arg>TradeModel</arg> </component> </components>
package com.snail.exam.s2dao; import java.sql.Timestamp; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class TradeModel { private static final Log log = LogFactory.getLog(TradeModel.class); private CustomerDao pCustomerDao; private ItemDao pItemDao; private OrderDao pOrderDao; public TradeModel(CustomerDao customerDao,ItemDao itemDao,OrderDao orderDao) { super(); pCustomerDao = customerDao; pItemDao = itemDao; pOrderDao = orderDao; } public boolean checkCreditFacility(long userId){ int currentCreditFacility = pOrderDao.sumCreditSale(userId); log.debug("現在の顧客番号"+userId+"の売掛金は"+currentCreditFacility+"です。"); CustomerBean customer = pCustomerDao.findCustomer(userId); int maxCreditFacility = customer.getCreditFacility(); log.debug("現在の顧客番号"+userId+"の与信枠は"+maxCreditFacility+"です。"); return currentCreditFacility < maxCreditFacility; } public boolean checkStock(long itemId,int amount ){ ItemBean item = pItemDao.findItemByPK(itemId); log.debug(item.getName() + "の在庫:" + item.getStock()); return amount < item.getStock(); } public long setAside(long userId,long itemId,int amount){ CustomerBean customer = pCustomerDao.findCustomer(userId); ItemBean item = pItemDao.findItemByPK(itemId); // 在庫を減らす item.setStock(item.getStock()-amount); pItemDao.update(item); // 受注をたてる OrderBean order = new OrderBean(); order.setAmount(amount); order.setCustomerId(customer.getId()); order.setItemId(item.getId()); Timestamp now = new Timestamp(System.currentTimeMillis()); order.setOnCreate(now); order.setOnUpdate(now); order.setStatus('0'); order.setTradePrice((int)(item.getPrice() * (1.0 - customer.getDiscountRate()))); pOrderDao.insert(order); return order.getId(); } }
checkCreditFacility?() | 与信枠チェック |
checkStock() | 在庫チェック |
setAside() | 在庫引き当て |
package com.snail.exam.s2dao; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class TradeService { private static final Log log = LogFactory.getLog(TradeService.class); private TradeModel pTradeModel; public TradeService(TradeModel tradeModel) { super(); pTradeModel = tradeModel; } /** * 受注処理を行います. * <pre> * 1.売掛金が与信枠を超えないかどうかを調べます. * 2.在庫があるかどうかを調べます * 3.在庫の引き当てを行います(Itemから在庫が減らされ、Orderテーブルに一行追加される) * 4.Order番号を返却します * </pre> * @param userId ユーザID * @param itemId 商品ID * @param amount 個数 * @return Order番号 * @throws Exception 受注処理が行えなかった */ public long order(long userId,long itemId,int amount) throws Exception{ if(!pTradeModel.checkCreditFacility(userId)){ throw new Exception("売掛金が与信枠を超えています"); } log.debug("与信チェックOK"); if(!pTradeModel.checkStock(itemId, amount)){ throw new Exception("在庫が足りません"); } log.debug("在庫チェックOK"); return pTradeModel.setAside(userId, itemId, amount); } }
package com.snail.exam.s2dao; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.seasar.framework.container.S2Container; import org.seasar.framework.container.factory.S2ContainerFactory; public class S2DAOExam4 { private static Log logger = LogFactory.getLog(S2DAOExam.class); public static void main(String[] args) { S2Container container = null; try { container = S2ContainerFactory.create("app.dicon"); TradeService service = (TradeService) container.getComponent(TradeService.class); long orderNo = service.order(1,1,10); logger.info("注文が入りました。注文番号:" + orderNo); } catch (Exception e) { e.printStackTrace(); } finally { if (container != null) { container.destroy(); } } } }
(log4jで出力したものを適宜編集しています)
トランザクションを開始しました。tx=[FormatId=4360, GlobalId=1230999349905/0, BranchId=] 物理的なコネクションを取得しました SELECT SUM(TRADE_PRICE * AMOUNT) FROM ORDER_TBL WHERE CUSTOMER_ID = 1 現在の顧客番号1の売掛金は635です SELECT CUSTOMER_TBL.ADDRESS, CUSTOMER_TBL.NAME, CUSTOMER_TBL.ID, CUSTOMER_TBL.CREDIT_FACILITY, CUSTOMER_TBL.DISCOUNT_RATE, CUSTOMER_TBL.ON_CREATE, CUSTOMER_TBL.ON_UPDATE FROM CUSTOMER_TBL WHERE CUSTOMER_TBL.ID = 1 現在の顧客番号1の与信枠は700です。 与信チェックOK SELECT ITEM_TBL.NAME, ITEM_TBL.ID, ITEM_TBL.ON_CREATE, ITEM_TBL.ON_UPDATE, ITEM_TBL.FULL_PRICE, ITEM_TBL.STOCK FROM ITEM_TBL WHERE ITEM_TBL.ID = 1 ぬののふくの在庫:100 在庫チェックOK UPDATE ITEM_TBL SET NAME = 'ぬののふく', ON_CREATE = '2009-01-03 22.45.24', ON_UPDATE = '2009-01-04 01.15.51', FULL_PRICE = 20, STOCK = 90 WHERE ID = 1 AND ON_UPDATE = '2009-01-03 22.45.24' INSERT INTO ORDER_TBL (STATUS, ON_CREATE, ON_UPDATE, CUSTOMER_ID, ITEM_ID, AMOUNT, TRADE_PRICE) VALUES ('0', '2009-01-04 01.15.51', '2009-01-04 01.15.51', 1, 1, 10, 18) トランザクションをコミットしました。tx=[FormatId=4360, GlobalId=1230999349905/0, BranchId=] 物理的なコネクションを閉じました 注文が入りました。注文番号:5
トランザクションを開始しました。tx=[FormatId=4360, GlobalId=1231000146634/0, BranchId=] 物理的なコネクションを取得しました SELECT SUM(TRADE_PRICE * AMOUNT) FROM ORDER_TBL WHERE CUSTOMER_ID = 1 現在の顧客番号1の売掛金は815です SELECT CUSTOMER_TBL.ADDRESS, CUSTOMER_TBL.NAME, CUSTOMER_TBL.ID, CUSTOMER_TBL.CREDIT_FACILITY, CUSTOMER_TBL.DISCOUNT_RATE, CUSTOMER_TBL.ON_CREATE, CUSTOMER_TBL.ON_UPDATE FROM CUSTOMER_TBL WHERE CUSTOMER_TBL.ID = 1 現在の顧客番号1の与信枠は700です。 トランザクションをロールバックしました。tx=[FormatId=4360, GlobalId=1231000146634/0, BranchId=] 物理的なコネクションを閉じました java.lang.Exception: 売掛金が与信枠を超えています