Lock Select
업무 요건상 동시에 처리할 수 없는 데이터를 Select할 때 Oracle에서 제공하는 FOR UPDATE 키워드를 사용하여 Lock 처리한다. WAIT 시간은 업무에 따라 알맞게 설정한다.
1. 형식
NOWAIT : 해당 Row가 Lock 상태일 때 바로 SQL 에러(ORA-00054)를 발생시킨다.
WAIT X : 해당 Row가 Lock 상태일 때 X초 재시도 후 SQL 에러(ORA-30006)을 발생시킨다.
SELECT
A.ROWID AS "rowId"
, A.FEDU_EMP_NO AS feduEmpNo
, A.FEDU_EMP_NM AS feduEmpNm
, A.FEDU_OCCP_NM AS feduOccpNm
FROM SMP_EMP_TST A
WHERE A.FEDU_EMP_NO = #{feduEmpNo}
FOR UPDATE [NOWAIT | WAIT seconds]
2. 개발 및 유의사항
조회 Row가 Lock 상태이면 DasCannotAcquireLockException(caused by ORA-00054/ORA-30006)이 발생한다.
try {
dSmpEmpTst001.selectOneLock01(dSmpEmpTst000Dto, LockUpdate.FOR_UPDATE);
} catch (DasCannotAcquireLockException e) {
// DB LOCK 타임아웃 발생시 처리로직
}
3. DBIO 샘플
Options 에 [Lock Update] 를 체크한다. 단건/다건 Select 구문에 ROWID와 FOR UPDATE 구문을 추가한다.
팝업에서 작성된 SQL의 스키마를 지정한다.
4. Bean 샘플
@BxmCategory(logicalName = "Multi-Update 2")
public int modifyEmpInfBySelectOneLock(List<DSmpEmpTst000Dto> input)
throws DefaultApplicationException {
logger.debug("============== START ==============");
logger.debug("input = {}", input);
dSmpEmpTst001 = DefaultApplicationContext.getBean(dSmpEmpTst001, DSmpEmpTst001.class);
int modifyCnt = 0;
/**
* @BXMType Loop
*/
for (DSmpEmpTst000Dto dSmpEmpTst000Dto : input)
{
/**
* @BXMType DbioCall
* @Desc Get lock for a row to update
*/
LockUpdater<DSmpEmpTst000Dto> lockUpdaterDSmpEmpTst = dSmpEmpTst001.selectOneLock01(dSmpEmpTst000Dto, LockUpdate.FOR_UPDATE);
DSmpEmpTst000Dto lockDSmpEmpTst000Dto = lockUpdaterDSmpEmpTst.updatable();
/**
* @BXMType LogicalArea
* @Desc Mapping data to update
*/
{
// Generated by code generator [[
lockDSmpEmpTst000Dto.setFeduEmpNo(dSmpEmpTst000Dto.getFeduEmpNo());
lockDSmpEmpTst000Dto.setFeduEmpNm(dSmpEmpTst000Dto.getFeduEmpNm());
lockDSmpEmpTst000Dto.setFeduOccpNm(dSmpEmpTst000Dto.getFeduOccpNm());
lockDSmpEmpTst000Dto.setFeduMngrEmpNo(dSmpEmpTst000Dto.getFeduMngrEmpNo());
lockDSmpEmpTst000Dto.setFeduHireDt(dSmpEmpTst000Dto.getFeduHireDt());
lockDSmpEmpTst000Dto.setFeduPayAmt(dSmpEmpTst000Dto.getFeduPayAmt());
lockDSmpEmpTst000Dto.setFeduDeptNo(dSmpEmpTst000Dto.getFeduDeptNo());
// Generated by code generator ]]
}
/**
* @BXMType DbioCall
* Update single employee info
*/
modifyCnt = lockUpdaterDSmpEmpTst.update();
/**
* @BXMType IF
* @Desc If there are no modified row
*/
if (modifyCnt != 1) {
/**
* @BXMType ApplicationException
* @Desc throw application exception if there are no modified row
*/
throw new DefaultApplicationException("BXME60003", new Object[] { lockDSmpEmpTst000Dto.getFeduEmpNo() } );
}
}
logger.debug("output = {}", modifyCnt);
logger.debug("============== END ==============");
return modifyCnt;
}