SQLAlchemy 2.0

김민범·2025년 8월 7일

DB

목록 보기
12/12

1. 주요 변경사항 (What's Changed)

Core 변경사항

  • select() 구문 변경: 키워드 인수를 더 이상 받지 않고, 컬럼들은 위치 인수로 전달
  • execute() 메소드 강화: 더 엄격해졌으며, 실행 옵션이 더 중요해짐
  • Result 객체: named tuple처럼 동작하는 Row 객체 사용
  • 연결/트랜잭션: "Connectionless" 실행과 "bound metadata" 제거

ORM 변경사항

  • Query와 Core Select 통합: ORM Query가 Core의 select()와 통합됨
  • 세션 변경: Autocommit 모드 제거, autobegin 지원 추가
  • 관계형 로딩: "Dynamic" 로더가 "Write Only"로 대체됨
  • 결과 고유화: ORM 행이 기본적으로 고유화되지 않음

2. 마이그레이션 단계

2.0으로 마이그레이션하는 7단계

  1. 1.3 애플리케이션 작동 확인
  2. 1.4 애플리케이션으로 업그레이드
  3. Python 3.7+ 사용 (2.0 최소 요구사항)
  4. RemovedIn20Warning 활성화
  5. 모든 RemovedIn20Warning 해결
  6. Engine에서 future 플래그 사용
  7. Session에서 future 플래그 사용

3. 주요 구문 변경 예시

3.1 select() 구문 변경

# 1.x 구문 (더 이상 지원안됨)
# stmt = select([table.c.x, table.c.y], whereclause=table.c.id == 5)

# 2.0 구문
from sqlalchemy import select
stmt = select(table.c.x, table.c.y).where(table.c.id == 5).order_by(table.c.id)

3.2 Session.get() 메소드 변경

# 1.x 구문
user_obj = session.query(User).get(5)

# 2.0 구문
user_obj = session.get(User, 5)

3.3 Connection.execute() 변경

# 2.0에서 권장하는 방법
with engine.connect() as conn:
    result = conn.execute(text("SELECT * FROM table WHERE id = :id"), {"id": 1})
    conn.commit()  # 필요시 명시적 커밋

3.4 ORM 쿼리 스타일 변경

# 1.x 스타일
users = session.query(User).filter(User.name == "john").all()

# 2.0 스타일 (권장)
from sqlalchemy import select
stmt = select(User).where(User.name == "john")
users = session.execute(stmt).scalars().all()

4. 새로운 기능들

4.1 Declarative 개선

# 새로운 import 위치
from sqlalchemy.orm import declarative_base, declared_attr  # 2.0
# from sqlalchemy.ext import declarative_base, declared_attr  # 1.x (구식)

4.2 Registry 기반 매핑

from sqlalchemy.orm import registry, relationship

mapper_reg = registry()
Base = mapper_reg.generate_base()

# 명령형 매핑
mapper_reg.map_imperatively(
    SomeClass, 
    some_table, 
    properties={"related": relationship(SomeRelatedClass)}
)

4.3 Future 엔진 사용

from sqlalchemy import create_engine, text

# future=True로 2.0 스타일 활성화
engine = create_engine("postgresql+psycopg2:///", future=True)

with engine.connect() as conn:
    conn.execute(text("INSERT INTO table (x) VALUES (:x)"), {"x": 10})
    conn.commit()

5. 대량 업데이트/삭제 작업

# 1.x 스타일
session.query(User).filter(User.name == "sandy").update(
    {"password": "foobar"}, synchronize_session="fetch"
)

# 2.0 스타일
from sqlalchemy import update
stmt = (
    update(User)
    .where(User.name == "sandy")
    .values(password="foobar")
    .execution_options(synchronize_session="fetch")
)
session.execute(stmt)

6. 주의사항

6.1 제거된 기능들

  • Connectionless 실행: metadata.create_all() 등에 명시적 엔진 필요
  • Query.join() 체이닝: 리스트 형태의 속성 체이닝 제거
  • Session autocommit: 자동 커밋 모드 제거

6.2 호환성 확인 방법

# 환경 변수로 2.0 경고 활성화
import os
os.environ["SQLALCHEMY_WARN_20"] = "1"

이러한 변경사항들은 SQLAlchemy를 더 일관되고 명시적으로 만들어주며, Core와 ORM 사이의 차이점을 줄여줍니다.

0개의 댓글