개요
SQLAlchemy에서 모델과 DB를 연결하기 위해서는, 객체-관계 매핑 (ORM)을 수행하는데
'사용 방법(문법)과 코드 스타일'에 있어 명령형, 선언형 두가지 방향성을 제시한다.
물론 뻔한말로 프로젝트의 요구사항과 팀 방향성에 따라 선택 될 수 있다.
Declarative Mapping은 더 간결하고, 유지보수가 쉬우며, 대부분의 일반적인 사용 사례에 적합한 반면,
Imperative Mapping은 더 복잡하고, 맞춤형 데이터베이스 매핑이 필요한 경우 등에 유리
두 방법을 혼합하여 사용할 수도 있으며, 상황에 따라 적절한 방식을 선택하는 것이 중요
Declarative Mapping 방식에서도 기존에 사용하던 방식 외에 2.0이 되면서 Mapped, mapped_column 이란 문법을 통해 좀더 orm을 잘 쓸 수 있게 업그레이드 되었는데, 특징도 살펴본다.
SQLAlchemy - Imperative Mapping (명령형) 방식
코드 스타일 : 클래스와, 테이블을 개별적으로 정의하여 명시적인 매핑
메타데이터 관리 : registry()의 metadata를 직접 관리 해주어야 한다.
매핑 설정 : map_imperatively와 같은 함수로 테이블과 클래스를 직접 매핑한다.
비교적 잘 사용 안되는 방식
from sqlalchemy import create_engine, Table, Column, Integer, String
from sqlalchemy.orm import registry, sessionmaker
# 메타데이터 객체 관리
mapper_registry = registry()
# DB 유저 테이블
user_table = Table(
"user",
mapper_registry.metadata,
Column("id", Integer, primary_key=True),
Column("name", String(50)),
Column("age", Integer),
)
# Python 유저 객체
class User:
id:int
name:str
age:int
# 테이블과 클래스의 매핑 설정
mapper_registry.map_imperatively(User, user_table)
# 데이터베이스 설정
engine = create_engine('sqlite:///:memory:')
mapper_registry.metadata.create_all(engine) # 테이블 생성
Session = sessionmaker(bind=engine)
session = Session()
# 데이터 삽입 예시
user = User(name="Bob", age=30)
session.add(user)
session.commit()
SQLAlchemy - Declarative Mapping (선언형) - 2.0 이전
클래스와 테이블을 동시에 정의하고
클래스 선언시 테이블의 이름, 컬럼 타입, 제약 조건 등을 클래스 속성(__tablename__, Column(Integer))으로 정의
Base 라는 모든 ORM 클래스의 공통 베이스 클래스를 declarative_base()를 통해 생성
Base.metadata를 이용한 자동화된 메타데이터 관리로 편의성이 좋음
별도의 매핑 없이 클래스 정의 자체가 매핑을 포함함
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import declarative_base, sessionmaker
# 1. engine 생성
engine = create_engine('sqlite:///example.db')
# 2. Base 객체 생성
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String)
age = Column(Integer)
# 3. (Optional) 해당 Engine의 DB에 Metadata를 바탕으로 테이블 생성
Base.metadata.create_all(engine)
# 4. 세션 팩토리 및 세션 객체 생성
Session = sessionmaker(bind=engine)
session = Session()
# 데이터 추가
new_user = User(name='Alice', age=30)
session.add(new_user)
session.commit()
SQLAlchemy - Declarative Mapping (선언형) - 2.0 이후
SQLAlcheym 2.0 이 되면서 PEP-484 (Type Hinting 에 관한 내용)에 따라 Mapped와 mapped_column() 이란 문법을 이용하는 방법이 추가 되었다
목표는 Python 객체 모델과 Database 모델 간에 실제 SQL 테이블을 설명할 수 있는 메타데이터(MetaData)를 동시에 정의함.
즉 ex) Python int 객체는 해당 DB 테이블에서의 Integer 를 뜻하는 정보를 MetaData에 넣어놓는다.
조금 더 기능적으로 다양성을 위해 ORM Layer에서 간결하게 사용할 수 있도록 추가된 문법
Column 으로 선언하던 것이 -> Mapped와 mapped_column 으로 바뀜
from typing import Optional
from sqlalchemy import Integer, String, ForeignKey
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
# declarative base class
class Base(DeclarativeBase):
pass
# an example mapping using the base
class User(Base):
__tablename__ = "user"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str]
fullname: Mapped[str] = mapped_column(String(30))
nickname: Mapped[Optional[str]]
'DB > Sqlalchemy' 카테고리의 다른 글
[SQLAlchemy] (5-2) DB driver 종류 (postgresql) (1) | 2024.09.18 |
---|---|
[SQLAlchemy] (5-1) DB driver 종류 (mysql/maria) (0) | 2024.09.16 |
[SQLAlchemy] (4) DML 예시 (by sqlalchemy 2.0) (2) | 2024.09.08 |
[SQLAlchemy] (2) Core 방식 vs ORM 방식 (1) | 2024.08.25 |
[SQLAlchemy] (1) 기본 개념 및 동작 방식 (0) | 2024.08.24 |