Replies: 1 comment
-
|
1. BitSet의 핵심 개념 BitSet 은 내부적으로 long[] 배열을 사용하여 비트를 저장합니다.
2. 주요 특징 및 장점
3. 주요 메서드 활용법 기초 조작 BitSet bitSet = new BitSet(); // 기본 64비트 크기로 시작
// 특정 인덱스 비트를 true로 설정
bitSet.set(10);
bitSet.set(20, 25); // 20~24번 인덱스를 true로
// 비트 값 확인
boolean status = bitSet.get(10); // true
// 비트 반전
bitSet.flip(10); // true였던 10번을 false로
// 비트 삭제 (false로 설정)
bitSet.clear(20);집합 연산 두 개의 BitSet 을 비교하거나 합칠 때 매우 유용합니다. BitSet s1 = new BitSet();
BitSet s2 = new BitSet();
s1.and(s2); // 교집합 (s1에 결과 저장)
s1.or(s2); // 합집합
s1.xor(s2); // 대칭 차집합
s1.andNot(s2); // 차집합‘ 내부 구현의: "Words" 방식 소스 코드 상단에서 볼 수 있듯이, BitSet 은 데이터를 long[] words 배열에 저장합니다.
|
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Active Record 패턴과 상태 관리 (Dirty Checking) 분석
jOOQ는 ORM(Object-Relational Mapping) 프레임워크인 JPA(Hibernate)와는 다른 철학을 가지고 있습니다. JPA가 전역적인 영속성 컨텍스트(EntityManager)를 두어 엔티티의 상태 변화를 감지하고 쿼리를 지연(Lazy) 생성한다면, jOOQ는 각 레코드 객체 스스로가 상태를 관리하고 데이터베이스 오퍼레이션을 수행할 수 있는 Active Record 패턴을 선택적으로 지원한다.
Active Record Pattern
데이터베이스의 테이블의 행을 하나의 객체로 매핑하고, 그 객체 자체가 자신의 데이터베이스 상태(저장, 수정, 삭제)를 직접 관리하도록 하는 아키텍처 패턴이다.
순수 JDBC를 다룰 때 반복적으로 작성해야 했던 INSERT, UPDATE 구문과 파라미터 매핑 작엄을 객체의 메서드 호출로 대처할 수 있어서 객체 지향적인 데이터 접근을 가능하게 한다.
1. 상태 관리:
AbstractRecord와BitSet모든 레코드의 조상인
AbstractRecord는 각 컬럼의 상태를 효율적으로 관리하기 위해java.util.BitSet을 사용한다.📌 실제 코드 구조
내부 필드 (Fields)
1 Object[] values현재 레코드가 가지고 있는 최신 데이터 배열입니다.
사용자가
set()을 호출하면 이 배열의 값이 업데이트됩니다.2 Object[] originals데이터베이스에서 처음 읽어왔을 때의 원본 데이터 배열입니다.
modified()판단이나 낙관적 잠금(Optimistic Locking) 시 비교 대상으로 사용됩니다.3 BitSet touched어떤 컬럼의
record.set(FIELD, value)메서드가 호출되었는지를 비트 마스크로 관리합니다.boolean[]보다 메모리 효율이 뛰어나며 비트 연산으로 빠른 상태 확인이 가능합니다.4 boolean fetched이 레코드가 DB에서 조회된 것인지(
true), 사용자가newRecord()로 새로 생성한 것인지(false)를 나타냅니다.2. Dirty 상태 전이 과정:
set()메서드 분석사용자가
record.set(FIELD, value)를 호출할 때 일어나는 내부 로직입니다.📌
AbstractRecord.java소스 로직touched비트셋에 기록합니다.3. 정교한 변경 감지:
touchedvsmodifiedjOOQ는 설정(
Settings)에 따라 "무엇을 변경된 것으로 보고 쿼리에 포함할 것인가?"를 두 가지 방식으로 정의합니다.이는
Tools.recordDirtyTrackingPredicate에 의해 결정됩니다.AbstractRecord.java)touched(기본값)touched(index)touched.get(index)modifiedmodified(index)touched.get(index) && !deepEqual(values[i], originals[i])4. 동적 SQL 생성 및 실행:
update()&store()레코드의 상태가 어떻게 실제 SQL로 변환되는지에 대한 실행 경로입니다.
store()의 분기 로직 (UpdatableRecordImpl.store0())fetched == true: 이미 DB에 존재하는 레코드로 판단하여UPDATE를 수행합니다.fetched == false: 새로운 레코드로 판단하여INSERT를 수행합니다.Surgical Update (부분 업데이트) 과정
addTouchedValues()(inTableRecordImpl): 모든 필드를 순회하며dirty.test(this, index)가true인 필드만 선별합니다.query.addValue(field, value): 선별된 필드만UpdateQuery객체에 담습니다.UPDATE BOOK SET TITLE = ? WHERE ID = ?와 같이 수정된 컬럼만 포함된 최적화된 SQL이 생성됩니다.UpdatableRecord인터페이스데이터베이스 커넥션과 렌더링 정보를 담고 있는
Configuration을 내부에 유지할 수 있다.이 연결 상태에 따라 레코드의 상태가 나뉜다.
Detached (분리됨): 개발자가 new 키워드나 DSLContext.newRecord()로 직접 생성한 상태이다. 데이터베이스와 연결 고리가 없다.Attached (연결됨): 데이터베이스에서 조회(featch)해 왔거나, attch() 메서드를 통해 Configuration이 주입된 상태이다. 이 상태에서만 객체 스스로 쿼리를 실행할 수 있다.store()메서드의 내부 분기 로직사용자가
record.store()를 호출하면, jOOQ는 내부적으로store0()메서드를 통해INSERT를 할지UPDATE를 할지 결정한다.UpdatableRecordImpl.java분석fetched플래그만 보는 것이 아니라,기본키(Primary Key)의 변경 여부를 민감하게 체크한다.
만약 기존 레코드의 ID를 바꾸고
store()를 하면, jOOQ는 이를 새로운 행 삽입으로 처리한다.아키텍처 다이어그램 (Visualization)
[레코드 상태 변화 및 쿼리 생성 흐름]
sequenceDiagram participant User participant Record as BookRecord (UpdatableRecord) participant State as Internal State (BitSet & Arrays) participant DB as Database Note over User, DB: 1. Fetch Record (DB에서 조회) User->>DB: fetchById(1) DB-->>Record: {id:1, title:"Old Title"} Record->>State: values=[1, "Old Title"], originals=[1, "Old Title"], touched=[0, 0], fetched=true Note over User, DB: 2. Update Value (Dirty 마킹) User->>Record: setTitle("New Title") Record->>State: values[1] = "New Title", touched.set(1) Note right of State: touched=[0, 1] (Dirty!) Note over User, DB: 3. Store / Update (쿼리 생성) User->>Record: update() Record->>State: Check touched BitSet (Index 1 is true) Record->>Record: Build SQL: "UPDATE BOOK SET TITLE = ? WHERE ID = ?" Record->>DB: Execute with ["New Title", 1]JPA와의 비교 분석
Self-contained)EntityManager)set()호출 시 즉시 비트셋 마킹touched비트셋 기반의 명시적 동적 쿼리Beta Was this translation helpful? Give feedback.
All reactions