데이터베이스/ORM

SQLAlchemy 사용

DS지니 2021. 3. 22. 01:02
728x90
반응형

1) 패키지 설치

pip install sqlalchemy     # 1.3 버전

pip install --pre sqlalchemy   # 1.4Beta 버전

 

2) 데이터베이스와의 연결

코어의 엔진으로 연결 :  추상화를 통해(Pool) DBAPI 사용가능해짐 Connection Pooling

 

from sqlalchemy import create_engine

engine = create_engine("데이터베이스 주소")

# 예시 engine = create_engine("sqlite:///:memory:")
  •  .///  -  디렉토리 상대적 경로
  •  .////  -  절대적 경로
  •  :memory:  - 스토리지가 아닌 메모리에서 임시적으로 데이터 베이스 사용. 접속 끊는 순간 데이터베이스 날아감. 

 

3) Mapping 매핑

데이터베이스의 구조와 코드를 연결.

데이터베이스에 user라는 테이블이 존재하면 코드 상에도 이 테이블과 정상적으로 연결 될 수 있도록 user 테이블을 코드로 구현함.

잘못 매핑하거나 매핑이 되어 있지 않은 경우에는 코드 상에서 변경 된 내용을 데이터베이스에 적용할 떄 문제가 발생함.

 

<ORM에서 매핑하는 법은 2가지가 있다.>

1) ORM에게 다룰 테이블을 알려주는 방법

2) 데이터베이스의 테이블에 매핑될 테이블 클래스들을 코드로 구현하는 방법

 

 

하지만! SQLAlchemy는 2가지 방법을 하나로 묶어서 작업할 수 있게 합니다.!

# SQLAlchemy 1.3 버전
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()


# SQLAlchemy 1.4 버전
from sqlalchemy.orm import declarative_base
Base = declarative_base()

- declarative_base( ) : 상속클래스들을 자동으로 인지하고 알아서 매핑해줌.

 

 

 

4) 테이블 생성

데이터 베이스 연결과 SQLAlchemy의 Base 클래스를 만들었다면 그 다음은 테이블 클래스를 만들어주면 됩니다.

 

from sqlalchemy import Column, Integer, String

class User(Base):

    __tablename__ = "user"
    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    age = Column(Integer)

 

  • Column, Integer, String 등 불러오기
  • Varchar(num)는 String(num)으로 변경
  • 테이블 이름을 따로 지정하지 않을 시에는 SQLAlchemy에서 기본 설정으로 클래스 이름의 소문자로 변경해줌.
  • auto increment 기능 : 칼럼 타입이 숫자이고 기본키에 포함될 때 자동으로 설정
  • nullable 기본값은 True (NOT NULL=False와 같음) 그러므로, Not null이 True라면 nullable=False 설정
  • 인스턴스 조회 (선택)
class User(Base):
    __tablename__ = "user"

    (... 생략 ...)

    def __repr__(self):
        return f"User {self.id}: {self.name}"
        

tom = User(name='Tom', age=20)

print(tom) 
#=> "User 1: Tom"

 

 

5) 스키마 생성

테이블 설정을 완료하면 스키마를 생성합니다.

메타데이터를 보관하고 있는 Base를 이용해 스키마를 간단하게 생성해줄 수 있습니다.

Base.metadata.create_all(engine)

 

6) Session 생성

docs.sqlalchemy.org/en/14/orm/session_basics.html

ORM이 편리한 이유 중 하나는 매우 중요한 요소인 Session 객체 덕분입니다.

Session 객체는 ORM으로 매핑된 객체들을 지속적 작업을 관리해주는 역할을 합니다. 

또 다른 말로 "holding zone" 이라고 표현하기도 합니다. ORM 객체 자체는 세션 내에서 (=Identity map이라는 구조 내) 유지됩니다.

 

코드로 데이터베이스 관련 작업을 하게 되면 바로 데이터베이스 시스템으로 작업 내용을 보내는 것이 아니라 세션객체에서 일시적으로 관리를 하게 됩니다. 커밋을 해야 세션에서는 작업 내용들을 데이터베이스 시스템에 보냅니다.

 

반대로 데이터베이스로부터 데이터를 쿼리하는 SQL 쿼리문을 작성해 커밋을 날리게 될 경우에도 세션 객체가 일시적으로 보관하게 됩니다. 따라서 사용자는 세션 객체를 통해 데이터 베이스 관련 객체들을 관리하게 됩니다.

 

3가지 방법 모두 같습니다. 만약 엔진이 바인딩 되지 않으면 UnboundExecutionError 가 일어납니다.

 

방법1)

from sqlalchemy.orm import sessionmaker

session = sessionmaker()   #하나의 빈 세션 인스턴스 생성

session = sessionmaker(bind=engine)  # 엔진 넣기

 

방법2)

from sqlalchemy.orm import sessionmaker

session = sessionmaker()

session.configure(bind=engine)

 

방법3)

from sqlalchemy.orm import Session # 세션클래스 가져오기

session = Session()

session.configure(bind=engine)

 

 

7) 데이터베이스 작업

이제 설정이 모두 끝났습니다. 이제 데이터베이스 작업을 할 수 있습니다.

ORM은 초기설정만 잘 되있으면 나머지 데이터베이스 작업은 수월합니다.

 

ORM에서는 클래스, 인스턴스 등 '객체'를 통해 작업합니다.(객체지향) 따라서 제일 먼저 필요한 것은 'user'클래스의 인스턴스를 생성하는 것 입니다.  그리고 Session을 이용해 데이터를 추가하거나(add) 삭제(Delete) 할 수 있습니다.

 

순서 : 인스턴스 생성 - 세션 엔진 보내기(세션에서 인스턴스 인지) - add/delete 메소드 - 세션 커밋하기

# 클래스의 인스턴스 생성
tom = User(name="Tom", age=20)
session = Session(bind=engine)

# 데이터 추가/Create
session.add(Tom)
session.commit()

# 데이터 삭제/Delete,
session.delete(Tom)
session.commit()

만약 커밋 전에 세션이 종료가 되면 SQL의 ROLLBACK이 실행됩니다. 데이터베이스에 저장을 하기 위해서는 꼭 커밋을 해야 기록이 됩니다!

 

8) Session 종료

마지막엔 연결을 닫아줍시다. 그래야 세션으로 인한 불필요한 오버헤드도 제거하고 데이터베이스의 연결도 안정적으로 종료한다는 것을 명시할 수 있습니다.

 

 

<주의점>

1. connecting pool 에 연결된 모든 connection 리소스를 풀어줍니다. 이 과정에서 진행 중이던 transaction 또한 자동으로 rollback됩니다.

2. 세션에서부터 모든 객체를 제거합니다. 즉, 세션에 로딩되었던 파이썬 객체들이 있었다면 이제는 연결이 제거된 상태로 변경이 됩니다. 또한 세션을 커밋하게 되는 과정에서 데이터베이스와 연결된 객체들은 더 이상 연결이 되지 않아 기능을 잃게 됩니다. 

728x90
반응형

'데이터베이스 > ORM' 카테고리의 다른 글

SQLAlchemy 정의, 구조  (0) 2021.03.22
ORM 장점과 단점, 언제 사용?  (0) 2021.03.21
ORM(Object-Relational Mapper)  (0) 2021.03.21
ORM 관련 영상 및 자료  (0) 2021.03.21