Files
document-haness/docs/clean-architecture-backend-template/tech-log-studio/transaction-and-consistency-models/concept/concept-adapter-outbound-persistence-jpa-c26.md
T
DongHyeonkaandClaude Opus 5 b2963105a8 docs(keycloak-session-store): import the session-storage lab as a new project
The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.

Follows the import procedure in README.md.

  source/     the originating repository verbatim — 78 documents, 28 SVGs,
              8 manifests, plus .source-revision recording the commit
  final/      the SSOT
    document.md   729 lines written from the 29 experiment documents, not
                  concatenated: what was predicted, what was measured, and
                  where the measurement itself was wrong
    evidence/raw    125 outputs, flattened to <experiment>__<file> because
                    the originals collided (01-baseline.txt appeared three
                    times) and the audit only globs the top level
    evidence/meta   one per raw file; command and exitCode are null and the
                    README says why rather than inventing them
    evidence/browser  22 captures
    assets/       three diagrams through techviz
    .techviz/     their VizSpecs

A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.

Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.

verify-pipeline.py passes. audit-records.py reports no issues.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 22:51:59 +09:00

3.1 KiB

kind, slug, title, topic, project, status, sourceRevision, rootTreeNode, evidenceCapturedOn, assets, evidence, source, module
kind slug title topic project status sourceRevision rootTreeNode evidenceCapturedOn assets evidence source module
CONCEPT adapter-outbound-persistence-jpa-c26 쓰기 경로마다 트랜잭션 소유가 다르다 transaction-and-consistency-models clean-architecture-backend-template 게시 전 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 concept:adapter-outbound-persistence-jpa-c26 2026-09-01
key file
adapter-outbound-persistence-jpa-c26 ../../../final/evidence/rendered/adapter-outbound-persistence-jpa-c26.svg
key file
adapter-outbound-persistence-jpa-c26-diagram ../../../final/assets/diagrams/adapter-outbound-persistence-jpa-c26.svg
../../../final/evidence/raw/adapter-outbound-persistence-jpa-c26.txt
원본 분석 절은 analysis/05-adapter-outbound-persistence-jpa.md#L1819 이다.
adapter-outbound-persistence-jpa

쓰기 경로마다 트랜잭션 소유가 다르다

HibernateBulkDmlExecutor는 arbitrary JPQL을 아무 데서나 실행하는 helper가 아니고, HibernateStatelessSessionRunner는 이 platform에서 transaction ownership 예외를 명시적으로 드러낸다.

본문

HibernateBulkDmlExecutor는 arbitrary JPQL string을 아무 데서나 실행하는 helper가 아니다. operation name 등록, affected-row expectation, persistence-context cleanup, transaction requirement를 contract로 둔다. bulk DML은 managed entity lifecycle을 우회하므로 ordinary entity save와 같은 audit/lifecycle guarantee를 기대하면 안 된다.

쓰기 경로마다 다른 소유 모델

:::evidence key="adapter-outbound-persistence-jpa-c26-diagram" alt="쓰기 경로에서 일반 repository adapter 와 bulk DML 과 StatelessSession runner 로 화살표가 나가고 화살표마다 트랜잭션 소유 방식이 붙은 구조" caption="쓰기 경로마다 다른 소유 모델" zoom="false" :::

HibernateBulkDmlExecutor 참조 위치

:::evidence key="adapter-outbound-persistence-jpa-c26" alt="코드베이스에서 HibernateBulkDmlExecutor 를 검색한 출력 7줄. 이 기록이 세는 참조가 그 출력에 그대로 보인다." caption="HibernateBulkDmlExecutor 코드베이스 검색 — 7줄 · exit 0" zoom="true" :::

사용 중이라고 주장하지 않는 이유

support matrix도 이를 Advanced capability로 분리한다. 현재 production business consumer는 확인되지 않았고 PostgreSQL integration fixture에서 실제 behavior를 qualification한다. 따라서 "runtime에서 사용 중"이라고 주장하지 않는다.

이름만 row cap 이던 문제는 고쳐져 있다

HibernateStatelessSessionRunner는 오히려 이 platform에서 transaction ownership 예외를 명시적으로 드러낸다 — 일반 repository adapter는 application transaction boundary에 참여하고, StatelessSession runner는 그렇지 않다. 과거 review에서는 caller가 선언한 maxRows가 실제 affected rows와 연결되지 않는 문제가 있었다. 현재는 StatelessWorkResult(value, affectedRows)를 요구하고 cap 초과 시 commit 전에 rollback한다.