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

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

## 1. Role

### JBSbatKKAdChgFinAddRun.lockKaisenTgSvkei()

This method implements **optimistic concurrency control** (via a pessimistic "SELECT ... FOR UPDATE WAIT" pattern) for a **service contract line** (`KK_T_KAISEN_TG_SVKEI`) in the batch processing domain. Its primary purpose is to acquire an exclusive database lock on a specific service contract line record and validate that the record has not been modified since the batch's snapshot was taken, thereby preventing lost updates during concurrent batch execution. The method constructs a primary-key-based query by combining the service contract number (`svcKeiNo`) and the service contract line detail number (`svcKeiKaisenUcwkNo`), performs the locked read, and then compares the stored update timestamp (`UPD_DTM`) against the batch's expected update timestamp (`updDtm`). If the timestamps differ (indicating the row was modified by another transaction or session), it throws a `JBSbatBusinessException` with error code `EKKB0360KE`, canceling the batch operation for that service contract line. The method is a shared utility called by the batch's `execute()` entry point and is used by other update methods in the same class (e.g., `updateKaisenTgSvkei`) to guard database writes.

**Design pattern:** Guard / Lock-before-update — this method acts as a gatekeeper that must succeed before any subsequent UPDATE operation on the same table is permitted.

## 2. Processing Pattern (Detailed Business Logic)

```mermaid
flowchart TD
    START(["lockKaisenTgSvkei(svcKeiNo, svcKeiKaisenUcwkNo, updDtm)"])

    START --> INIT_RESULT["Initialize resultMap = null"]
    INIT_RESULT --> TRY_START["try block start"]

    TRY_START --> CREATE_WHERE["Create whereMap with new JBSbatCommonDBInterface()"]
    CREATE_WHERE --> SET_SVC_KEI["whereMap.setValue(SVC_KEI_NO, svcKeiNo)"]
    SET_SVC_KEI --> SET_UCWK["whereMap.setValue(SVC_KEI_KAISEN_UCWK_NO, svcKeiKaisenUcwkNo)"]
    SET_UCWK --> SELECT["db_KK_T_KAISEN_TG_SVKEI.selectByPrimaryKeysForUpdateWait(whereMap)"]
    SELECT --> CHECK_LOCK["Check: updDtm equals resultMap.getString(UPD_DTM)"]

    CHECK_LOCK --> LOCK_MISMATCH{updDtm != UPD_DTM}
    LOCK_MISMATCH -->|true| THROW_LOCK["throw JBSbatBusinessException(EKKB0360KE, 回線対象サービス契約)"]
    LOCK_MISMATCH -->|false| END_NODE(["Return void - Lock acquired"])

    SELECT -->|JBSbatBusinessException| CATCH_BIE["catch JBSbatBusinessException"]
    SELECT -->|Exception| CATCH_EX["catch Exception"]
    CATCH_BIE --> THROW_BIE["throw JBSbatBusinessException(EKKB0360KE, 回線対象サービス契約)"]
    CATCH_EX --> THROW_EX["throw JBSbatBusinessException(EKKB0360KE, 回線対象サービス契約)"]
    THROW_BIE --> END
    THROW_EX --> END
    THROW_LOCK --> END
```

**Processing summary:**

1. **Initialization** — Creates a null-safe `resultMap` reference and prepares a `try` block.
2. **Where-map construction** — Builds a key map using `JBSbatCommonDBInterface`, setting the service contract number and line detail number as primary key criteria.
3. **Pessimistic locked read** — Calls `selectByPrimaryKeysForUpdateWait()` on the `db_KK_T_KAISEN_TG_SVKEI` accessor to lock the target row in the database. This uses a "SELECT FOR UPDATE WAIT" strategy (waiting for the row lock rather than failing immediately with a deadlock error).
4. **Exception handling (catch JBSbatBusinessException)** — If the locked read fails (e.g., row not found, lock timeout), the original catch-all error code `CS00002W` was replaced with a domain-specific code `EKKB0360KE` that includes the business context: "回線対象サービス契約" (Service Contract Line) plus the service contract number and line detail number for traceability.
5. **Exception handling (catch Exception)** — All other unexpected exceptions are caught and re-wrapped as `JBSbatBusinessException` with the same error code `EKKB0360KE`.
6. **Timestamp conflict check** — After a successful read, the method compares `updDtm` (the batch's snapshot of the update timestamp) with the actual `UPD_DTM` value returned from the database. If they differ, it means the record was modified between the batch's data loading phase and this lock acquisition — a classic write-write conflict. The method throws `EKKB0360KE` to signal this conflict.
7. **Return** — If no exception is thrown and timestamps match, the method returns `void` successfully, indicating the row is locked and valid for subsequent UPDATE operations.

## 3. Parameter Analysis

| No | Parameter Name | Type | Business Description |
|----|---------------|------|---------------------|
| 1 | `svcKeiNo` | `String` | Service Contract Number — the unique identifier of a service contract in the telecom billing domain. Used as a primary key column (`SVC_KEI_NO`) to identify the target row. [-> SVC_KEI_NO="SVC_KEI_NO" (JBSbatKK_T_KAISEN_TG_SVKEI.java)] |
| 2 | `svcKeiKaisenUcwkNo` | `String` | Service Contract Line Detail Number — the sub-line item identifier within a service contract. Combined with `svcKeiNo`, it forms the composite primary key. [-> SVC_KEI_KAISEN_UCWK_NO="SVC_KEI_KAISEN_UCWK_NO" (JBSbatKK_T_KAISEN_TG_SVKEI.java)] |
| 3 | `updDtm` | `String` | Expected Update Date/Time — the snapshot of the record's `UPD_DTM` column captured earlier in the batch's data loading phase. Used for optimistic lock validation: if the database value differs from this, a conflict is detected. [-> UPD_DTM="UPD_DTM" (JBSbatKK_T_KAISEN_TG_SVKEI.java)] |

**Instance fields read by this method:**

| Field | Type | Description |
|-------|------|-------------|
| `db_KK_T_KAISEN_TG_SVKEI` | `JBSbatSQLAccess` | Database accessor for the service contract line table, initialized with `D_TBL_NAME_KK_T_KAISEN_TG_SVKEI` |

## 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_KAISEN_TG_SVKEI.selectByPrimaryKeysForUpdateWait` | — | `KK_T_KAISEN_TG_SVKEI` | Pessimistic locked read of the service contract line by composite primary key. Acquires an exclusive row lock (SELECT FOR UPDATE WAIT) to prevent concurrent updates. |
| R | `resultMap.getString` | — | In-memory | Reads the `UPD_DTM` value from the result map returned by the SELECT FOR UPDATE to validate the update timestamp. |

### CRUD Summary:

| CRUD | SC / CBS | SC Code | Entity / DB | Operation Description |
|------|----------|---------|-------------|----------------------|
| R | `JBSbatSQLAccess.selectByPrimaryKeysForUpdateWait(whereMap)` | — | `KK_T_KAISEN_TG_SVKEI` | Reads one row from the Service Contract Line table using composite primary key (SVC_KEI_NO, SVC_KEI_KAISEN_UCWK_NO) with a database-level exclusive row lock. This is the core concurrency control mechanism. |
| R | `JBSbatCommonDBInterface.getString(JBSbatKK_T_KAISEN_TG_SVKEI.UPD_DTM)` | — | In-memory | Extracts the update timestamp from the query result for comparison against the batch's expected value. |

## 5. Dependency Trace

### Callers

| # | Caller (Screen/Batch) | Call Chain (Full Path to this Method) | Terminal (SC / CRUD / Entity) |
|---|----------------------|--------------------------------------|-------------------------------|
| 1 | Batch: `JBSbatKKAdChgFinAddRun.execute()` | `JBSbatKKAdChgFinAddRun.execute()` -> `lockKaisenTgSvkei(svcKeiNo, svcKeiKaisenUcwkNo, updDtm)` | `selectByPrimaryKeysForUpdateWait [R] KK_T_KAISEN_TG_SVKEI` |

### Description

This method is a **private utility** called exclusively by its own class's batch entry point `execute()`. It does not appear to be called from any screen (KKSV*) or external batch entry point. It serves as the lock acquisition step within the batch's data flow — typically called immediately before an UPDATE operation on the `KK_T_KAISEN_TG_SVKEI` table to ensure no other transaction has modified the row.

**Terminal operations reached from this method:**
- `selectByPrimaryKeysForUpdateWait(whereMap)` → [R] `KK_T_KAISEN_TG_SVKEI` (Service Contract Line table)
- `getString(JBSbatKK_T_KAISEN_TG_SVKEI.UPD_DTM)` → [R] In-memory result map

## 6. Per-Branch Detail Blocks

**Block 1** — TRY `(exception handling block)` (L1267)

> Wraps the locked read operation in a try-catch block. Two exception handlers are present: one for `JBSbatBusinessException` and one for general `Exception`. Both were updated in the ST2-2013-0001403 modification (20130316) to use a domain-specific error code instead of the generic `CS00002W`.

| # | Type | Code |
|---|------|------|
| 1 | SET | `resultMap = null` // Initialize result holder |
| 2 | SET | `whereMap = new JBSbatCommonDBInterface()` // Create where criteria map |
| 3 | SET | `whereMap.setValue(JBSbatKK_T_KAISEN_TG_SVKEI.SVC_KEI_NO, svcKeiNo)` // Set service contract number as key [-> SVC_KEI_NO (JBSbatKK_T_KAISEN_TG_SVKEI.java)] |
| 4 | SET | `whereMap.setValue(JBSbatKK_T_KAISEN_TG_SVKEI.SVC_KEI_KAISEN_UCWK_NO, svcKeiKaisenUcwkNo)` // Set line detail number as key [-> SVC_KEI_KAISEN_UCWK_NO (JBSbatKK_T_KAISEN_TG_SVKEI.java)] |
| 5 | CALL | `resultMap = db_KK_T_KAISEN_TG_SVKEI.selectByPrimaryKeysForUpdateWait(whereMap)` // Locked read from service contract line table |
| 6 | CATCH | `catch (JBSbatBusinessException bie)` // Catches domain-specific exceptions (e.g., row not found) |
| 7 | EXEC | `throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0360KE, new String[]{"回線対象サービス契約", svcKeiNo + ", " + svcKeiKaisenUcwkNo})` // Throws domain-specific error: Service Contract Line lock failure [-> EKKB0360KE (JPCBatchMessageConstant.java)] |
| 8 | CATCH | `catch (Exception ex)` // Catches all other exceptions |
| 9 | EXEC | `throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0360KE, new String[]{"回線対象サービス契約", svcKeiNo + ", " + svcKeiKaisenUcwkNo})` // Same error code for all exceptions (ST2-2013-0001403 modification) |

**Block 2** — IF `(timestamp conflict check)` (L1291)

> After the locked read succeeds, validates that the actual database update timestamp matches the batch's expected value. A mismatch means the row was modified after the batch loaded its data but before it acquired the lock — a write-write conflict.

| # | Type | Code |
|---|------|------|
| 1 | IF | `!updDtm.equals(resultMap.getString(JBSbatKK_T_KAISEN_TG_SVKEI.UPD_DTM))` // Timestamp conflict detected [-> UPD_DTM (JBSbatKK_T_KAISEN_TG_SVKEI.java)] |
| 2 | EXEC | `throw new JBSbatBusinessException(JPCBatchMessageConstant.EKKB0360KE, new String[]{"回線対象サービス契約", svcKeiNo + ", " + svcKeiKaisenUcwkNo})` // Throws conflict error |

## 7. Glossary

| Term | Type | Business Meaning |
|------|------|------------------|
| `svcKeiNo` | Field | Service Contract Number — unique identifier of a telecom service contract. Equivalent to Japanese: サービス契約番号 (Saabisu Keiyaku Bangou). |
| `svcKeiKaisenUcwkNo` | Field | Service Contract Line Detail Number — sub-line item within a service contract. Equivalent to Japanese: サービス契約回線内訳番号 (Saabisu Keiyaku Kaisen Uchiwari Bangou). |
| `updDtm` | Field | Update Date/Time — timestamp of the last modification to the record. Equivalent to Japanese: 更新年月日時分秒 (Koushin Nengetsunichijifunbyou). Used for optimistic concurrency validation. |
| `KK_T_KAISEN_TG_SVKEI` | Table | Service Contract Line Table — the database table storing service contract line item records. "回線対象サービス契約" (Kaisen Taishou Saabisu Keiyaku) = Service Contract Line. |
| `selectByPrimaryKeysForUpdateWait` | Method | Database access method that performs a "SELECT ... FOR UPDATE WAIT" query — acquires a row-level exclusive lock while waiting (rather than failing immediately on lock contention). |
| `EKKB0360KE` | Error Code | Domain-specific batch error code for service contract line lock failures. Introduced in ST2-2013-0001403 to replace the generic `CS00002W`. |
| `JBSbatCommonDBInterface` | Interface | Common database interface for key-value map operations used to construct WHERE criteria. |
| `JBSbatSQLAccess` | Class | SQL access abstraction layer providing database operations (select, insert, update, delete) for batch processing. |
| `JBSbatBusinessException` | Exception | Framework exception for business logic errors, carrying error codes and contextual message parameters. |
| `KK_T_` prefix | Convention | Database table name prefix in this system, indicating a core batch processing table. |
| `回線対象サービス契約` | Japanese term | Service Contract Line — a line item within a service contract, representing a specific service provision line. |
| CS00002W | Error Code | Generic batch error code, superseded by domain-specific codes (e.g., EKKB0360KE) in the ST2-2013-0001403 modification. |
