サンプルプロジェクトはこちら 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: 売掛金が与信枠を超えています