SQLAlchemy

GreenBean·2022년 7월 26일
0
post-thumbnail

SQLAlchemy

SQLAlchemy란?

SQLAlchemy 공식 문서

보통의 비망록: SQLAlchemy 시작하기
Dork's port: SQLAlchemy 사용하기

  • Python에서 사용가능한 ORM(Object-Relational Maping)
    • ORM은 말그대로 객체(Object)와 관계(Relation)를 연결해주는 것
    • 데이터베이스의 데이터를 ← 매핑 → Object 필드
  • SQLAlchemy 객체 관계형 매퍼는 데이터베이스 테이블을 이용해 사용자가 정의한 파이썬 클래스의 메소드와 각각의 행을 나타내는 인스턴스로 표현
    • 객체와 각 연관된 행들의 모든 변경점들이 자동으로 동기되어 인스턴스에 반영되며, 그와 동시에 사용자가 정의한 클래스와 각 클래스 사이에 정의된 관계에 대해 쿼리할 수 있는 (Unit of work이라 하는)시스템을 포함하고 있음
  • 이 ORM에서 사용하는 SQLAlchemy 표현 언어는 ORM의 구성 방식과도 같음
    • SQL 언어 튜토리얼에서는 직접적인 의견을 배제한 채 데이터베이스들의 초기에 어떻게 구성해 나가야 하는지에 대해 설명하는 반면 ORM은 고수준의, 추상적인 패턴의 사용 방식과 그에 따른 표현 언어를 사용하는 방법을 예로 보여줌
  • 사용 패턴과 각 표현 언어가 겹쳐지는 동안, 초기와 달리 공통적으로 나타나는 사항에 대해 표면적으로 접근
    • 먼저 사용자가 정의한 도메인 모델서부터 기본적인 저장 모델을 새로 갱신하는 것까지의 모든 과정을 일련의 구조와 데이터로 접근하게 해야함
    • 또 다른 접근 방식으로는 문자로 된 스키마와 SQL 표현식이 나타내는 투시도로부터 명쾌하게 구성해, 각 개별적인 데이터베이스를 메시지로 사용할 수 있게 해야 함
  • 장점
    • 객체 지향적인 코드로 비즈니스 로직에 집중 가능
    • 재사용 및 유지보수 편리성이 증가
    • DBMS에 대한 종속성이 줄어듬
  • 단점
    • ORM 만으로 서비스를 구현하기 어려움
    • 프로시저가 많은 시스템에서는 장점을 가져가기 어려움

사용 방법

버전 확인

import sqlalchemy

print sqlalchemy.__version__

접속

  • 예시: sqlite 데이터베이스 사용
    • create-engine()을 이용해 접속
from sqlalchemy import create_engine

engine = create_engine('sqlite:///:memory:', echo=True)
  • echo는 로그를 위한 플래그
    • 파이썬 표준 logging 모듈 사용
    • 순수 SQL 코드를 보여줌
  • engine은 선언만 해서 바로 연결되는게 아니라 첫 실행이 될 때 연결
print engine.execute("select 1").scalar()
  • ORM을 사용할 때는 위처럼 engine을 직접 이용할 필요는 없음
    • 맨 처음 연결 할 때 작성하고 ORM 사용하면 됨

매핑 선언

  • ORM에서는 처음에 데이터베이스 테이블을 써먹을 수 있게 설정한 다음 직접 정의한 클래스에 맵핑을 해야함
    • SQLAlchemy에서는 두가지가 동시에 이뤄지는데 Declarative 란걸 이용해 클래스를 생성하고 실제 데이터베이스 테이블에 연결
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
  • 이렇게 해두면 몇개든 매핑 클래스를 만들 수 있음
    • 매핑 클래스 내에서 데이터베이스의 컬럼을 나타내는 Column 클래스, 각 컬럼의 데이터타입을 나타내는 Integer, String 클래스를 불러와야 함
from sqlalchemy import Column, Integer, String


class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    fullname = Column(String)
    password = Column(String)

    def __init__(self, name, fullname, password):
        self.name = name
        self.fullname = fullname
        self.password = password

    def __repr__(self):
        return "<User('%s', '%s', '%s')>" % (self.name, self.fullname, self.password)
  • 위 User 클래스는 __tablename__에서 정의한 테이블에 맵핑되고 primary key인 id와 name, fullname, password 컬럼을 가짐
  • 메소드는 마음껏 만들어도 상관없음
    • 파이썬 기본 class와 같음
    • __init____repr__도 생성 가능
    • Base를 상속하지만 이는 단지 최소의 설정만 담당
  • Declarative System으로 만들어진 이 클래스는 table metadata를 가지게 되는데 이것이 사용자 정의 클래스와 테이블을 연결해주는 기능을 수행
    • 예전엔 이 metadata를 만들고 클래스에 맵핑해서 썼는데 그 방식을 Classical Mapping이라고 함
    • 그 예전 방식에서는 Table이라는 데이터 구조와 Mapper 객체로 클래스와 맵핑
# metadata 보는 방법
User.__table__

# mapper 클래스
User.__mapper__
  • Declarative 기반 클래스는 모든 Table 객체들을 metadata로 정의해두고 .metadata 속성을 통해 접근할 수 있게 도와줌
  • 아직 위의 예제 클래스는 테이블이 생성이 되지 않은 상태인데 metadata를 통해 손쉽게 생성할 수 있도록 도와준다. 테이블을 생성할 때 metadata.create_all() 로 생성할 수 있는데 이 메소드를 호출하면 engine으로 연결된 데이터베이스에 테이블을 생성
Base.metadata.create_all(engine)
profile
🌱 Backend-Dev | hwaya2828@gmail.com

0개의 댓글