# Business Logic — JBSbatKKAdChgFinAddRun.lockSvkeiKaisenUw() [31 LOC]

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

## 1. Role

### JBSbatKKAdChgFinAddRun.lockSvkeiKaisenUw()

This method implements an **exclusive pessimistic lock** on the service contract line detail table (`KK_T_SVKEI_KAISEN_UW`). It is the gatekeeper that ensures a single processing thread holds an up-to-date row before any subsequent modifications can proceed, preventing lost-update concurrency defects in the batch-driven service contract change pipeline. The method performs a `SELECT FOR UPDATE WAIT` query against the database using two primary key columns — `SVC_KEI_KAISEN_UCWK_NO` and `GENE_ADD_DTM` — which together identify a unique row within the line-detail partition. After acquiring the lock, it validates that the incoming `updDtm` (update timestamp) matches the timestamp currently stored in the database row, enforcing a timestamp-based optimistic check atop the pessimistic lock. If the timestamps diverge, it throws `EKKB0360KE` to signal that another process has already modified the row. This method is called directly from `execute()` in the same class, serving as a pre-modification safeguard within the larger service contract addition/change batch flow. The design follows a **try-catch with timestamp validation** pattern, combining pessimistic database-level locking with application-level concurrency protection.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["lockSvkeiKaisenUw(svcKeiKaisenUcwkNo, geneAddDtm, updDtm)"])
    INIT["Initialize resultMap = null"]
    TRY_START["Try Block"]
    CREATE_WHEN_MAP["Create whereMap = new JBSbatCommonDBInterface()"]
    SET_SVC_KEY["whereMap.setValue(SVC_KEI_KAISEN_UCWK_NO, svcKeiKaisenUcwkNo)"]
    SET_GENE_DTM["whereMap.setValue(GENE_ADD_DTM, geneAddDtm)"]
    SELECT_LOCK["db_KK_T_SVKEI_KAISEN_UW.selectByPrimaryKeysForUpdateWait(whereMap)"]
    CATCH_BIZ["Catch JBSbatBusinessException"]
    CATCH_BIZ_THROW["Throw EKKB0360KE - Service Contract Line Detail"]
    CATCH_GEN["Catch Exception"]
    CATCH_GEN_THROW["Throw EKKB0360KE - Service Contract Line Detail"]
    CMP_UPD["Compare updDtm with resultMap.getString(UPD_DTM)"]
    CMP_NOT_EQUAL["updDtm != resultMap.UPD_DTM ?"]
    THROW_STALE["Throw EKKB0360KE - Stale Update Detected"]
    RETURN_OK["Return (void)"]
    END_NODE(["Return / Next"])

    START --> INIT --> TRY_START --> CREATE_WHEN_MAP --> SET_SVC_KEY --> SET_GENE_DTM --> SELECT_LOCK
    TRY_START -.-> CATCH_BIZ
    TRY_START -.-> CATCH_GEN
    CATCH_BIZ --> CATCH_BIZ_THROW
    CATCH_GEN --> CATCH_GEN_THROW
    CATCH_BIZ_THROW --> END_NODE
    CATCH_GEN_THROW --> END_NODE
    SELECT_LOCK --> CMP_UPD
    CMP_UPD --> CMP_NOT_EQUAL
    CMP_NOT_EQUAL -->|True| THROW_STALE
    CMP_NOT_EQUAL -->|False| RETURN_OK
    THROW_STALE --> END_NODE
    RETURN_OK --> END_NODE
```

**CRITICAL — Constant Resolution:**

| Constant | Resolved Value | Business Meaning |
|----------|---------------|------------------|
| `JBSbatKK_T_SVKEI_KAISEN_UW.SVC_KEI_KAISEN_UCWK_NO` | `"SVC_KEI_KAISEN_UCWK_NO"` | Service contract line detail number (primary key column) |
| `JBSbatKK_T_SVKEI_KAISEN_UW.GENE_ADD_DTM` | `"GENE_ADD_DTM"` | Generation registration date/time (primary key column) |
| `JBSbatKK_T_SVKEI_KAISEN_UW.UPD_DTM` | `"UPD_DTM"` | Update date/time (stale-lock detection column) |
| `JPCBatchMessageConstant.EKKB0360KE` | `"EKKB0360KE"` | Batch error code — "Service Contract Line Detail" (row not found / update conflict) |
| `KK_T_SVKEI_KAISEN_UW` | Table name | Service contract line detail table |

**Block-level constant used in error message:** The Japanese literal `"サービス契約回線内訳"` translates to "Service Contract Line Detail" and is embedded in the error message passed to `EKKB0360KE`.

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `svcKeiKaisenUcwkNo` | `String` | Service contract line detail number — the primary key that uniquely identifies a specific line item within a service contract. This is the main lookup key used to locate the database row for locking. |
| 2 | `geneAddDtm` | `String` | Generation registration date/time — the secondary primary key that identifies a specific version/revision of the line detail record. Together with `svcKeiKaisenUcwkNo`, it forms a composite primary key for precise row selection. |
| 3 | `updDtm` | `String` | Update date/time — the expected current value of the `UPD_DTM` column. Used in a post-lock validation to detect if another process has already modified the row since this method was invoked. |

**Instance fields read:**

| Field | Type | Business Description |
|-------|------|---------------------|
| `db_KK_T_SVKEI_KAISEN_UW` | `JBSbatSQLAccess` | Database access handler for the `KK_T_SVKEI_KAISEN_UW` table, initialized in the parent class setup. |

## 4. CRUD Operations / Called Services

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

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `db_KK_T_SVKEI_KAISEN_UW.selectByPrimaryKeysForUpdateWait` | - | `KK_T_SVKEI_KAISEN_UW` | Performs `SELECT FOR UPDATE WAIT` on the service contract line detail table, acquiring an exclusive pessimistic lock on the identified row. Blocks if another transaction holds the lock, rather than failing immediately. |
| R | `resultMap.getString` | - | In-memory | Reads the `UPD_DTM` field from the locked row's result map to compare against the expected timestamp. |

**Full CRUD classification:**

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `JBSbatSQLAccess.selectByPrimaryKeysForUpdateWait` | - | `KK_T_SVKEI_KAISEN_UW` | Read with exclusive lock — pessimistic row-level locking on the service contract line detail table using composite PK (`SVC_KEI_KAISEN_UCWK_NO`, `GENE_ADD_DTM`). The WAIT mode ensures the database blocks instead of raising an immediate lock conflict. |
| R | `JBSbatCommonDBInterface.getString` | - | In-memory result | Read — retrieves the `UPD_DTM` column value from the in-memory result set returned by the select operation, used for stale-data detection. |

## 5. Dependency Trace

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

No screen/batch entry points found within 8 hops. Direct callers found: 1 methods.
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 | `JBSbatKKAdChgFinAddRun.execute()` -> `lockSvkeiKaisenUw` | `selectByPrimaryKeysForUpdateWait [R] KK_T_SVKEI_KAISEN_UW` |

## 6. Per-Branch Detail Blocks

**Block 1** — [TRY-CATCH] `(Exception handling around DB lock acquisition)` (L1229)

> Attempts to acquire an exclusive lock on the service contract line detail row. Builds a WHERE clause from the composite primary key, executes the locked SELECT, and catches both specific and generic exceptions to standardize error output.

| # | Type | Code |
|---|------|------|
| 1 | SET | `resultMap = null;` // Initialize result map reference |
| 2 | SET | `whereMap = new JBSbatCommonDBInterface();` // Create WHERE condition container |
| 3 | SET | `whereMap.setValue(JBSbatKK_T_SVKEI_KAISEN_UW.SVC_KEI_KAISEN_UCWK_NO, svcKeiKaisenUcwkNo)` // Set primary key: service contract line detail number |
| 4 | SET | `whereMap.setValue(JBSbatKK_T_SVKEI_KAISEN_UW.GENE_ADD_DTM, geneAddDtm)` // Set primary key: generation registration timestamp |
| 5 | CALL | `resultMap = db_KK_T_SVKEI_KAISEN_UW.selectByPrimaryKeysForUpdateWait(whereMap);` // Pessimistic lock: SELECT FOR UPDATE WAIT on `KK_T_SVKEI_KAISEN_UW` |
| 6 | CATCH | `catch (JBSbatBusinessException bie)` -> `throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0360KE, new String[]{"サービス契約回線内訳", svcKeiKaisenUcwkNo + ", " + geneAddDtm});` // ST2-2013-0001403対応 20130316 星野 — Error code `EKKB0360KE` with Japanese literal "サービス契約回線内訳" (Service Contract Line Detail) and composite key values. This replaced the generic `CS00002W` error code. |
| 7 | CATCH | `catch (Exception ex)` -> `throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0360KE, new String[]{"サービス契約回線内訳", svcKeiKaisenUcwkNo + ", " + geneAddDtm});` // Catches any remaining unexpected exceptions and converts to the same `EKKB0360KE` business exception for consistent error reporting. |

**Block 2** — [IF] `(updDtm mismatch — stale data detection)` (L1253)

> After successfully acquiring the lock, compares the incoming `updDtm` parameter against the timestamp stored in the database. If they differ, another process has modified the row since the caller last read it, indicating a stale-data condition.

| # | Type | Code |
|---|------|------|
| 1 | SET | `storedUpdDtm = resultMap.getString(JBSbatKK_T_SVKEI_KAISEN_UW.UPD_DTM)` // Read update timestamp from locked row |
| 2 | IF | `!updDtm.equals(storedUpdDtm)` — Condition: the incoming `updDtm` does NOT match the database value `[-> UPD_DTM="UPD_DTM"]` |
| 3 | THROW | `throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0360KE, new String[]{"サービス契約回線内訳", svcKeiKaisenUcwkNo + ", " + geneAddDtm});` // Same error code as Block 1 — indicates row was modified by another process since this transaction started. |

**Block 3** — [ELSE] `(updDtm matches — lock is valid)` (L1256)

> No explicit else block exists. When the condition in Block 2 is false (timestamps match), the method falls through and returns `void` normally. The caller is now guaranteed to hold a valid exclusive lock with a validated-up-to-date row.

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `svcKeiKaisenUcwkNo` | Field | Service Contract Line Detail Work Number — internal tracking ID for a specific line item within a service contract. Serves as the primary key for row identification. |
| `geneAddDtm` | Field | Generation Registration Date/Time — identifies a specific version/revision of a line detail record. Combined with `svcKeiKaisenUcwkNo`, forms a composite primary key. |
| `updDtm` | Field | Update Date/Time — the most recent modification timestamp of a row. Used for optimistic concurrency control to detect stale updates. |
| `KK_T_SVKEI_KAISEN_UW` | Table | Service Contract Line Detail Table — stores line-item breakdown data for service contracts. The `_UW` suffix typically denotes an "underlying" or detail child table. |
| `SVC_KEI_KAISEN_UCWK_NO` | Table Column | Service Contract Line Detail Number column in `KK_T_SVKEI_KAISEN_UW`. |
| `GENE_ADD_DTM` | Table Column | Generation Registration Date/Time column in `KK_T_SVKEI_KAISEN_UW`. |
| `UPD_DTM` | Table Column | Update Date/Time column in `KK_T_SVKEI_KAISEN_UW` — tracks the last time the row was modified. |
| `EKKB0360KE` | Error Code | Batch error constant — "Service Contract Line Detail" error. Used when a row is not found, locked by another process, or has been updated by another transaction (stale data). |
| `JBSbatSQLAccess.selectByPrimaryKeysForUpdateWait` | Method | Database-level pessimistic lock operation. Executes `SELECT FOR UPDATE WAIT` which acquires an exclusive row lock and blocks if the row is held by another transaction. |
| `JBSbatCommonDBInterface` | Class | In-memory map-like container used to hold WHERE clause parameters and query results. Supports `setValue(key, value)` and `getString(key)` operations. |
| `"サービス契約回線内訳"` | Japanese Literal | "Service Contract Line Detail" — the business domain term embedded in error messages, referring to the line-item breakdown of a service contract. |
| `ST2-2013-0001403` | Issue ID | JIRA/defect tracking ID. Corresponds to a 2013-03-16 modification by 星野 (Hoshino) that changed error handling from generic `CS00002W` to domain-specific `EKKB0360KE` with contextual error messages. |
| `_UW` (suffix) | Naming Convention | Denotes "underlying" or child/detail table. `KK_T_SVKEI_KAISEN_UW` is a child table of the service contract header table, holding line-item detail records. |
