You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Builder를 자연스럽게 보이게 하려면 fluent style이 잘 맞기 때문에 같이 잘 사용된다!
Type-safe Fluent API는?
체이닝만 되는 게 아니라, 각 단계에서 반환 타입을 다르게 해서 잘못된 순서나 잘못된 조합을 컴파일 단계에서 막는 방식
select(...).from(...).where(...) → ⭕️
select(...).where(...) → ❌
가능하게 하려면 “모든 메서드가 같은 타입을 반환”하면 안 되고, 각 단계마다 다른 인터페이스를 반환해야 한다!
select() 다음에는 from()만 호출 가능하고, where()를 먼저 못 부른다.
interfaceSelectStep {
FromStepselect(); // select -> from
}
interfaceFromStep {
WhereStepfrom(); // from -> where
}
interfaceWhereStep {
ConditionStepwhere(); // where -> ConditionStep
}
= staged builder / step builder 스타일!
jOOQ 코드를 보며 분석해보자!
jOOQ란 SQL language를 type safe Java API로 모델링하는 internal DSL
[일반 방식 (JDBC)]
"SELECT * FROM user WHERE id = 1"
문자열이라 → 오타 나도 컴파일 안 잡힘 / 순서 틀려도 모른다
이를 극복하기 위한 것이 [jooQ]👇
1. DSLContext
DSLContext 인터페이스란?
쿼리 조립을 시작하는 진입점 (Builder Entry Point)
DSLContextcreate = DSL.using(connection, dialect);
// Immediately fetch results after constructing a querycreate.selectFrom(MY_TABLE).where(MY_TABLE.ID.eq(1)).fetch();
/* selectFrom 내부 동작 원리: new SelectImpl(configuration(), null).from(table);*/
의미:
SelectImplquery = newSelectImpl(...); // 쿼리 객체 생성query.from(table); // FROM 정보 추가
“SELECT 쿼리를 나타내는 객체를 만들고, 거기에 FROM 정보를 넣는다”
→ 이렇게 내부에서 객체를 만들어서 상태를 계속 쌓는다.
왜 필요한가?
SQL을 한 번에 만드는 게 아니라
단계적으로 조립해야 하기 때문
→ Builder 패턴처럼 아래와 같은 구조가 필요함
쿼리 객체 생성 → 상태 추가 → 상태 추가 → 실행
결론: DSLContext는 완성된 SQL을 들고 있는 객체가 아니라“쿼리 조립을 시작하게 해주는 Builder entry point”다
2. Select*Step 인터페이스
각 SQL 단계별로 다음에 가능한 행동만 정의한 인터페이스 → staged builder의 핵심
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Builder 패턴 간단 용어설명
복잡한 객체를 한 번에 생성하지 않고, 단계적으로 조립해서 최종 객체를 만드는 방식
🤔 왜 Builder 패턴이 필요한가
[생성자만 사용하는 경우]
단점: 각 인자가 무슨 의미인지 읽기 어렵다. 선택 값이 많아질수록 생성자↑
[Builder 사용하는 경우]
Fluent API과 Builder 패턴
[Fluent API]
메서드 호출이 자연스럽게 이어지도록 설계한 API 스타일 = 문법 스타일
[Builder 패턴]
복잡한 객체를 단계적으로 조립하는 생성 패턴 = 객체 생성 방식
Builder를 자연스럽게 보이게 하려면fluent style이 잘 맞기 때문에 같이 잘 사용된다!Type-safe Fluent API는?
체이닝만 되는 게 아니라, 각 단계에서 반환 타입을 다르게 해서 잘못된 순서나 잘못된 조합을 컴파일 단계에서 막는 방식
가능하게 하려면 “모든 메서드가 같은 타입을 반환”하면 안 되고, 각 단계마다 다른 인터페이스를 반환해야 한다!
= staged builder / step builder 스타일!
jOOQ 코드를 보며 분석해보자!
jOOQ란 SQL language를 type safe Java API로 모델링하는 internal DSL
[일반 방식 (JDBC)]
"SELECT * FROM user WHERE id = 1"문자열이라 → 오타 나도 컴파일 안 잡힘 / 순서 틀려도 모른다
이를 극복하기 위한 것이 [jooQ]👇
1. DSLContext
DSLContext 인터페이스란?
쿼리 조립을 시작하는 진입점 (Builder Entry Point)
의미:
→ 이렇게 내부에서 객체를 만들어서 상태를 계속 쌓는다.
왜 필요한가?
→ Builder 패턴처럼 아래와 같은 구조가 필요함
쿼리 객체 생성 → 상태 추가 → 상태 추가 → 실행결론: DSLContext는 완성된 SQL을 들고 있는 객체가 아니라“쿼리 조립을 시작하게 해주는 Builder entry point”다
2. Select*Step 인터페이스
각 SQL 단계별로 다음에 가능한 행동만 정의한 인터페이스 → staged builder의 핵심
코드 참조
org.jooq.SelectSelectSteporg.jooq.SelectJoinSteporg.jooq.SelectWhereSteporg.jooq.SelectConditionStep핵심 구조
SelectWhereStep → where() → SelectConditionStep
SelectWhereStep인터페이스SelectConditionStep인터페이스왜 필요한가?
잘못된 SQL 순서를 막기 위해
3. DefaultDSLContext 내부 구조
DSLContext의 기본 구현체→
select(),selectFrom(),insertInto()같은 메서드를 호출했을 때 실제로 내부 구현 객체를 만들어서 쿼리 조립을 시작시키는 클래스실제 코드에서
1.
selectFrom(table)메서드2.
select(fields)메서드결론
jOOQ는
DSLContext(DefaultDSLContext)를 통해SelectImpl같은 내부 쿼리 객체를 생성하고,이 객체를 기반으로 SQL을 단계적으로 조립하는 Builder 구조를 가진다.
또한
Select*Step인터페이스를 통해 각 단계에서 가능한 SQL 문법을 타입으로 제한하여 잘못된 쿼리 조합을 컴파일 시점에 방지하는 Type-safe Fluent API를 제공한다.예를 들어 사용자가 이렇게 쓴다고 해보자.
겉으로 보면 한 줄짜리 메서드 체인처럼 보이지만, 내부적으로는 대충 이런 흐름에 가깝다.
Beta Was this translation helpful? Give feedback.
All reactions