Files
llm-wiki/raw/official-docs/spring-data-jpa-transactionality-spring-official.md

78 lines
7.4 KiB
Markdown

---
title: official-doc / Spring Data JPA — Transactionality (Spring Official Reference)
source_type: official-doc
url: https://docs.spring.io/spring-data/jpa/reference/jpa/transactions.html
archive_url:
related_branches: [feature-application-query-bypass-contract]
related_projects: [ca-skeleton]
tags: [spring-data, jpa, transaction, read-only, service-layer, unit-of-work, ca-skeleton]
created: 2026-06-04
last_reviewed: 2026-06-04
---
# Spring Data JPA — Transactionality (Spring Official Reference)
> Layer: `raw/official-docs/` — Spring Data JPA 공식 레퍼런스 "Transactionality" 섹션 verbatim 발췌.
> CrudRepository 의 기본 `@Transactional(readOnly=true)` 동작 + service layer transaction boundary 권고의 1차 근거.
> feature-application-query-bypass-contract 의 **트랜잭션 bypass 허용 여부 (D2)** 결정에 필요한 공식 벤더 입장.
## Parent / 활용 branch (필수)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| [[raw/branch-notes/feature-application-query-bypass-contract]] | D2 (read-only transaction 을 모든 읽기에 강제할지 vs autocommit 허용할지) 결정의 Spring 공식 권고 근거 — Spring Data 자체가 CrudRepository read method 에 `@Transactional(readOnly=true)` 를 기본 적용하며, service layer 에서 transaction boundary 를 선언하도록 권고 |
## 출처 / Source
- 원본 URL: https://docs.spring.io/spring-data/jpa/reference/jpa/transactions.html
- 아카이브 URL:
- 저자 / 조직: Spring Team (VMware/Broadcom) — 공식 reference documentation
- 발행일: ongoing (Spring Data JPA 4.0.5 / Spring Boot 3.4+, 2026-06-04 기준 최신)
- 마지막 확인일: 2026-06-04
## 왜 저장했는지 / Why archived
ca-tmpl read-only transaction bypass 의 공식 근거. Spring Data JPA 가 read method 에 기본 `@Transactional(readOnly=true)` 를 적용하는 이유와, Spring 팀이 service layer transaction boundary 를 권고하는 이유를 검증하기 위해 보관.
## 핵심 인용 / Key quotes (verbatim)
> [§Transactionality — Default transactional config from CrudRepository] "By default, methods inherited from `CrudRepository` inherit the transactional configuration from `SimpleJpaRepository`. For read operations, the transaction configuration `readOnly` flag is set to `true`. All others are configured with a plain `@Transactional` so that default transaction configuration applies."
> [§Transactionality — Declared query methods note] "Declared query methods (including default methods) do not get any transaction configuration applied by default. To run those methods transactionally, use `@Transactional` at the repository interface you define..."
> [§Transactionality — Service layer boundary recommendation] "While examples discuss `@Transactional` usage on the repository, we generally recommend declaring transaction boundaries when starting a unit of work to ensure proper consistency and desired transaction participation."
## Claims Extracted / 추출된 주장
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| SPRING-DATA-TX-C1 | `CrudRepository` 에서 상속된 **read operation** 메서드는 `@Transactional(readOnly=true)` 가 기본 적용됨 — `SimpleJpaRepository` 의 기본 설정을 상속 | [§Transactionality] "For read operations, the transaction configuration `readOnly` flag is set to `true`." | `official-vendor-doc` | Spring Data JPA repository 의 `CrudRepository` 상속 read method (`findById`, `findAll`, `existsById` 등) | custom `@Query` annotated method 또는 직접 선언한 query method 에는 자동 적용 안 됨 — 별도 `@Transactional` 필요 (C2) |
| SPRING-DATA-TX-C2 | **직접 선언한 query method** (default method 포함) 에는 transaction configuration 이 기본 적용되지 않음 — transactionally 실행하려면 별도 `@Transactional` 추가 필요 | [§Transactionality] "Declared query methods (including default methods) do not get any transaction configuration applied by default. To run those methods transactionally, use `@Transactional` at the repository interface you define..." | `official-vendor-doc` | Spring Data repository 에 직접 선언한 method (예: `findByUsernameAndStatus(...)`) | 이 method 들이 트랜잭션 없이 실행된다는 뜻 — JPA flush/clear 는 발생하지 않지만 단순 SELECT 는 autocommit 모드로 실행될 수 있음 |
| SPRING-DATA-TX-C3 | Spring 팀은 **"unit of work 시작 시점에서 transaction boundary 를 선언"** 하도록 권고 — 일관성 보장 및 원하는 transaction participation 을 위해 service layer 에서 선언하는 것이 일반 권고 | [§Transactionality] "we generally recommend declaring transaction boundaries when starting a unit of work to ensure proper consistency and desired transaction participation." | `official-vendor-doc` | transaction boundary 설계 결정 | repository 에 `@Transactional` 을 두면 안 된다는 강제는 아님 — `@Transactional` 위치(repository vs service)는 이 인용만으로 확정 불가. "generally recommend" 이지 "must" 아님 |
## Usage Boundaries / 적용 경계
- 이 자료가 직접 증명하는 것:
- `SPRING-DATA-TX-C1`: CrudRepository read method 의 `@Transactional(readOnly=true)` 기본 동작
- `SPRING-DATA-TX-C2`: 직접 선언 query method 의 기본 트랜잭션 미적용
- `SPRING-DATA-TX-C3`: Spring 팀의 service layer transaction boundary 권고 ("generally recommend")
- 이 자료가 증명하지 않는 것:
- `readOnly=true` 가 Hibernate flush mode / dirty check skip 이외에 어떤 DB 수준 최적화를 유발하는지 — 별도 Hibernate 문서 참조 필요
- "no-transaction read" 가 안전한 조건과 unsafe 조건 — 본 문서는 트랜잭션 없이 실행하는 것이 OK 인 케이스를 직접 정의하지 않음
- hexagonal architecture 의 application layer 에서 직접 `@Transactional` 을 쓰는 것이 허용되는지 — architecture 설계 규칙은 본 문서 범위 밖
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
- ca-tmpl 의 thin read path (controller → read port 직접) 에서 read port implementation 이 `@Transactional(readOnly=true)` 없이 실행될 때 Hibernate session 의 연결 방식 (OSIV off 환경)
- Spring Data JPA 의 `@Transactional(readOnly=true)` 기본 적용이 실제 Hibernate session flush mode 를 `MANUAL` 로 설정하는지 (`spring-tx-management-reference#SPRING-TX-MGR-C6` 과 결합)
## 메모 / Notes
- Spring Data JPA 4.x 기준 (Spring Boot 3.4+ 에서 기본)
- `SPRING-DATA-TX-C3` 의 "unit of work" 개념은 ca-tmpl 의 `QueryUseCase` + `TransactionPort.inRead` 패턴과 정합 — use case 가 unit of work 의 시작점
- 본 문서는 Spring Data 가 repository read method 에 이미 `readOnly=true` 를 default 적용한다는 사실을 확인하므로, application layer 에서 thin read path 를 허용할 경우 "transaction 없이 실행되는 read" 와 "readOnly transaction 으로 실행되는 read" 의 경계가 사용자가 명시적 주석을 어디에 두는가에 달려 있음을 시사
## Related / 관련
- [[raw/official-docs/spring-tx-management-reference]] — `@Transactional` 의 readOnly 속성 공식 정의 (SPRING-TX-MGR-C6)
- [[raw/official-docs/at-transactional-spring-official]] — `@Transactional` 의 기본 동작 및 proxy mode 제약
- [[raw/branch-notes/feature-application-port-usecase-contract]] — QueryUseCase + TransactionPort.inRead 선행 계약 (D9)