# Business Logic — JBSbatKKAdChgFinAddRun.lockKojiak() [30 LOC]

| Field | Value |
|-------|-------|
| Fully Qualified Name | `eo.business.service.JBSbatKKAdChgFinAddRun` |
| Layer | Service (Batch Service) |
| Module | `service` (Package: `eo.business.service`) |

## 1. Role

### JBSbatKKAdChgFinAddRun.lockKojiak()

This method implements an optimistic concurrency control mechanism for the Work Case (工事案件) entity in the address change / final addition batch processing pipeline. Its primary purpose is to acquire an exclusive row-level lock on a specific KU_T_KOJIAK record while simultaneously verifying that the record has not been modified by another batch process since the caller last read it. The method builds a keyed map to select the target record for update wait, catches any database-level locking contention or business rule violations and normalizes them into a single typed error (`EKKB0360KE`), and then performs a timestamp comparison between the caller-supplied `updDtm` value and the actual stored `UPD_DTM` column. If the timestamps differ, it signals that a concurrent modification has occurred, throwing the same business exception to abort the current batch transaction. The method is a shared private utility called from the `execute()` entry point, serving as a gatekeeper before the batch proceeds to modify Work Case records.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["lockKojiak(kojiakNo, updDtm)"])
    INIT["Initialize resultMap = null"]
    TRY_START["Enter try block"]
    WHERE_MAP["Create whereMap = new JBSbatCommonDBInterface()"]
    SET_WHERE["whereMap.setValue(KOJIAK_NO, kojiakNo)"]
    SELECT["db_KU_T_KOJIAK.selectByPrimaryKeysForUpdateWait(whereMap)"]
    SELECT_LABEL["READ KU_T_KOJIAK - Fetch and lock record for update"]
    CATCH_BIE["Catch JBSbatBusinessException"]
    CATCH_EX["Catch Exception"]
    THROW["throw JBSbatBusinessException(EKKB0360KE, workCaseLabel, kojiakNo)"]
    THROW_LABEL["Business Exception - Lock acquisition failed"]
    CHECK_TIMESTAMP{"updDtm == resultMap.getString(UPD_DTM)?"}
    MATCH["Timestamps match - method completes normally"]
    MISMATCH["Timestamps differ - throw JBSbatBusinessException(EKKB0360KE)"]
    RETURN(["Return to caller - Continue in execute()"])

    START --> INIT --> TRY_START
    TRY_START --> WHERE_MAP --> SET_WHERE --> SELECT --> SELECT_LABEL
    SELECT --> CATCH_BIE
    CATCH_BIE --> THROW --> THROW_LABEL
    SELECT --> CATCH_EX
    CATCH_EX --> THROW
    TRY_START --> CHECK_TIMESTAMP
    CHECK_TIMESTAMP --> |"Yes"| MATCH
    CHECK_TIMESTAMP --> |"No"| MISMATCH
    MATCH --> RETURN
    MISMATCH --> RETURN
    THROW --> RETURN
```

**Processing notes:**
- The method uses a `selectByPrimaryKeysForUpdateWait` pattern — this is a database-level row lock that waits for any existing locks on the target row before proceeding, effectively serializing access to the same Work Case record.
- Both exception branches converge on the same error message code (`EKKB0360KE`), which is parameterized with the work case label ("工事案件") and the specific work case number.
- The timestamp check provides optimistic concurrency control: even if the row lock is acquired, the caller's snapshot timestamp is compared against the current database value to detect modifications that occurred between the original read and the lock acquisition.

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `kojiakNo` | `String` | Work Case Number — the unique identifier for a work case record in the `KU_T_KOJIAK` table. Used as the primary key to locate and lock the specific record. This number corresponds to a physical installation or service modification task associated with an address change operation. |
| 2 | `updDtm` | `String` | Update Date/Time (年月日時分秒) — the timestamp value that was read from the `UPD_DTM` column of the Work Case record during a prior query. Used for optimistic concurrency validation: if the stored value differs, it indicates the record was modified by another process between the read and now. |

**Instance fields read:**

| Field | Type | Business Description |
|-------|------|---------------------|
| `db_KU_T_KOJIAK` | `JBSbatSQLAccess` | Database access handler for the `KU_T_KOJIAK` table. Initialized in the class setup phase with the table name constant `D_TBL_NAME_KU_T_KOJIAK = "KU_T_KOJIAK"`. |

## 4. CRUD Operations / Called Services

### Pre-computed evidence from code analysis graph:

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `JBSbatKU_T_KOJIAK.getString` | — | — | Calls `getString` in `JBSbatKU_T_KOJIAK` to read field values |
| R | `JBSbatFUMoveNaviData.getString` | — | — | Calls `getString` in `JBSbatFUMoveNaviData` |
| R | `JBSbatZMAdDataSet.getString` | — | — | Calls `getString` in `JBSbatZMAdDataSet` |
| - | `JDKStructuredMap.setValue` | — | — | Calls `setValue` in `JDKStructuredMap` |
| - | `JKKEohTvGuideAddCC.setValue` | — | — | Calls `setValue` in `JKKEohTvGuideAddCC` |
| - | `DKSV0101_DKSV0101OP_EDKA0010001BSMapper.setValue` | — | — | Calls `setValue` in `DKSV0101_DKSV0101OP_EDKA0010001BSMapper` |
| - | `DKSV0102_DKSV0102OP_EDKA0010001BSMapper.setValue` | — | — | Calls `setValue` in `DKSV0102_DKSV0102OP_EDKA0010001BSMapper` |
| - | `DKSV0103_DKSV0103OP_EDKA0010001BSMapper.setValue` | — | — | Calls `setValue` in `DKSV0103_DKSV0103OP_EDKA0010001BSMapper` |
| R | `JESC0101B010TPMA.getString` | — | — | Calls `getString` in `JESC0101B010TPMA` |
| R | `JESC0101B020TPMA.getString` | — | — | Calls `getString` in `JESC0101B020TPMA` |

### Direct method calls within `lockKojiak()` body:

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| — | `new JBSbatCommonDBInterface()` | — | — | Creates a new structured map object for building query parameters |
| — | `whereMap.setValue(KOJIAK_NO, kojiakNo)` | — | — | Sets the work case number as a query key on the where map |
| R | `db_KU_T_KOJIAK.selectByPrimaryKeysForUpdateWait(whereMap)` | — | `KU_T_KOJIAK` | Reads and locks a single row from the Work Case table using the primary key as a predicate. The `ForUpdateWait` variant acquires an exclusive row lock and waits if the row is already locked by another transaction. |
| — | `resultMap.getString(JBSbatKU_T_KOJIAK.UPD_DTM)` | — | — | Extracts the `UPD_DTM` timestamp value from the query result map for comparison |
| - | `new JBSbatBusinessException(EKKB0360KE, workCaseLabel, kojiakNo)` | — | — | Constructs and throws a business exception when lock acquisition fails or timestamps diverge |

**CRUD classification rationale:**
- `selectByPrimaryKeysForUpdateWait` is classified as **R** (Read) because its primary purpose is to retrieve a record, even though it also acquires an exclusive lock. No data is created, modified, or deleted.
- `setValue` calls on structured maps are classified as **—** (not CRUD) because they manipulate in-memory data structures, not persistent storage.

## 5. Dependency Trace

No screen/batch entry points found within 8 hops. Direct callers found: 1 method.
Terminal operations from this method: `selectByPrimaryKeysForUpdateWait` [R], `getString` [R]

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Batch: `JBSbatKKAdChgFinAddRun.execute()` | `execute()` → `lockKojiak(kojiakNo, updDtm)` | `db_KU_T_KOJIAK.selectByPrimaryKeysForUpdateWait [R] KU_T_KOJIAK` |

**Call chain details:**
- `JBSbatKKAdChgFinAddRun.execute()` is the main batch entry point for the address change / final addition processing. It calls `lockKojiak()` as a preparatory step to ensure exclusive access to a Work Case record before performing further modifications (such as marking a work case as fix-completed).
- The terminal operation `selectByPrimaryKeysForUpdateWait` on `KU_T_KOJIAK` is the sole database interaction performed by this method, resulting in a **Read** operation with an exclusive row lock.

## 6. Per-Branch Detail Blocks

**Block 1** — [TRY] `(exception handling boundary)` (L1337)

> Establishes the try block that encompasses the database access and timestamp validation. All exceptions (business or generic) are caught and re-thrown as a unified business exception `EKKB0360KE`.

| # | Type | Code |
|---|------|------|
| 1 | SET | `JBSbatCommonDBInterface resultMap = null;` // Initialize result holder |

**Block 1.1** — [BLOCK: try] `(database access section)` (L1339)

> Creates the query predicate and executes the row-locking select against the Work Case table.

| # | Type | Code |
|---|------|------|
| 1 | SET | `JBSbatCommonDBInterface whereMap = new JBSbatCommonDBInterface();` // Instantiate empty query map |
| 2 | CALL | `whereMap.setValue(JBSbatKU_T_KOJIAK.KOJIAK_NO, kojiakNo);` // Set primary key on where map — `KOJIAK_NO = "KOJIAK_NO"` → `[-> JBSbatKU_T_KOJIAK.KOJIAK_NO="KOJIAK_NO"]` |
| 3 | CALL | `resultMap = db_KU_T_KOJIAK.selectByPrimaryKeysForUpdateWait(whereMap);` // R — Fetch and lock the KU_T_KOJIAK row by primary key, waiting for lock acquisition |

**Block 1.2** — [CATCH] `(JBSbatBusinessException bie)` (L1346)

> Catches business-level exceptions from the database layer. Per ST2-2013-0001403 (20130316 Hoshino MOD), the old generic error `CS00002W` is replaced with the domain-specific `EKKB0360KE` error, parameterized with the work case label and number.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0360KE, new String[]{"工事案件", kojiakNo});` // Business exception — 工事案件 (Work Case) + work case number |

**Block 1.3** — [CATCH] `(Exception ex)` (L1351)

> Catches any other runtime exceptions from the database layer. Same handling as Block 1.2 — all exceptions are normalized to `EKKB0360KE` to signal a lock acquisition failure.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0360KE, new String[]{"工事案件", kojiakNo});` // Business exception — 工事案件 (Work Case) + work case number |

**Block 2** — [IF] `(optimistic concurrency check: timestamps differ)` (L1357)

> After the row lock is acquired, this block validates that the Work Case record has not been modified since the caller last read it. The condition compares the caller-supplied `updDtm` against the actual `UPD_DTM` stored in the database. If they differ, a business exception is thrown. This is a classic optimistic locking pattern that prevents lost-update anomalies in batch processing.

| # | Type | Code |
|---|------|------|
| 1 | EXEC | `resultMap.getString(JBSbatKU_T_KOJIAK.UPD_DTM)` // Read stored timestamp — `UPD_DTM = "UPD_DTM"` → `[-> JBSbatKU_T_KOJIAK.UPD_DTM="UPD_DTM"]` |
| 2 | SET | (implicit condition: `!updDtm.equals(resultMap.getString(JBSbatKU_T_KOJIAK.UPD_DTM))`) // If the caller's timestamp does NOT match the database timestamp |
| 3 | EXEC | `throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0360KE, new String[]{"工事案件", kojiakNo});` // Business exception — record was concurrently modified |

> **Note:** This is an if-block with no else branch. When the timestamps match, the method falls through to its natural end, returning `void` to the caller.

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `kojiakNo` | Field | Work Case Number (工事案件番号) — Unique identifier for a Work Case record. Represents a specific installation or modification task in the address change processing workflow. |
| `updDtm` | Field | Update Date/Time (更新年月日時分秒) — Timestamp of the last modification to a Work Case record. Used for optimistic concurrency control to detect concurrent modifications. |
| `KU_T_KOJIAK` | Table | Work Case Table — Core table storing Work Case records. "KU" prefix indicates it is a utility/master table (ユーティリティテーブル). Contains fields for work case number, work case status, service contract links, and timestamps. |
| `KOJIAK_NO` | Field | Work Case Number column in `KU_T_KOJIAK` — Primary key identifier for a Work Case record. |
| `UPD_DTM` | Field | Update Date/Time column in `KU_T_KOJIAK` — Records the timestamp when the Work Case record was last modified. Used for optimistic concurrency detection. |
| `EKKB0360KE` | Message Code | Business Exception code (エラーコード) — Indicates a Work Case processing error, specifically used for lock acquisition failure or timestamp mismatch in this method. The "KE" suffix likely denotes "Key Error" or "Keep Error" (競合エラー). |
| `selectByPrimaryKeysForUpdateWait` | Method | Database row-locking read — Selects a record by primary key and acquires an exclusive row-level lock, waiting if the row is currently locked by another transaction. Prevents concurrent modification of the same Work Case record. |
| `工事案件` | Japanese term | Work Case / Construction Case — A record representing a physical installation, modification, or removal task associated with a customer's address change. Each Work Case has a unique number and tracks its status through the processing lifecycle. |
| `JBSbatBusinessException` | Class | Business-level exception — Custom exception class used across the batch processing framework to signal domain rule violations or operational errors. Carries a message code and optional parameter strings for error message localization. |
| `JBSbatCommonDBInterface` | Class | Common database interface — An interface/abstract class for structured map-based query parameter and result handling. Provides `setValue` and `getString` methods for key-value data access. |
| `JBSbatSQLAccess` | Class | SQL access handler — Database access abstraction layer initialized with a table name constant. Provides `selectByPrimaryKeysForUpdateWait`, `updateByPrimaryKeys`, and other CRUD methods. |
| `D_TBL_NAME_KU_T_KOJIAK` | Constant | Database table name constant — Value: `"KU_T_KOJIAK"`. Used to initialize the `db_KU_T_KOJIAK` SQL access handler. |
| Address Change Batch (住所変更バッチ) | Business term | The address change / final addition batch processing pipeline — a scheduled batch job that processes address modification requests, including finalizing address change work cases and updating related service contracts. |
| `db_KU_T_KOJIAK` | Instance field | SQL access instance for the `KU_T_KOJIAK` table — Initialized during class setup via `new JBSbatSQLAccess(commonItem, D_TBL_NAME_KU_T_KOJIAK)`. |
