본문 바로가기
SQLAlchemy

SpringDataJPA 일부 구현해보기

by 스티브 십잡스 2024. 5. 5.

fetchJoin을 통해 eager loading을 사용하기 보다는 select 문에 객체들을 선언하고 명시적으로 조인을 사용하는 방식을 더 선호해서 사용하지 않지만, 깃허브에서 좋은 내용을 봐서 작성해봅니다.

from typing import Generic, TypeVar, Any, Sequence
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, insert

from .base import BaseEntity


EntityType = TypeVar("EntityType", bound=BaseEntity)


class BaseRepository(Generic[EntityType]):
    def __init__(
        self,
        model: type[EntityType],
    ) -> None:
        self._model = model
        
    async def get_by(self, session: AsyncSession, **kwargs: dict) -> EntityType | None:
        stmt = select(self._model)
        for k, v in kwargs.items():
            stmt = stmt.where(self._model.k == v)

        resp = await session.execute(stmt)
        return resp.scalar_one_or_none()

    async def get_all_by(self, session: AsyncSession, **kwargs: dict) -> Sequence[EntityType | None]:
        stmt = select(self._model)
        for k, v in kwargs.items():
            stmt = stmt.where(self._model.k == v)

        resp = await session.execute(stmt)
        return resp.scalars().all()

    async def save(self, session: AsyncSession, obj: Any) -> int:
        resp = await session.execute(insert(self._model).values(vars(obj)))
        session.commit()
        return resp.inserted_primary_key[0]

    async def save_all(self, session: AsyncSession, objs: list[Any]) -> list[int]:
        values = [vars(obj) for obj in objs]
        resp = await session.execute(insert(self._model).values(values))
        session.commit()
        return resp.inserted_primary_key

 

이것을 사용할 때는 아래와 같은 방식으로 사용할 수 있다.

class CustomRepository(BaseRepository[UserEntity]):
    async def get_by_id(
        self, 
        session: AsyncSession, 
        id: int,
    ) -> UserEntity | None:
        return await self.get_by(session, id=id)
      
    async def save(
        self,
        session: AsyncSession,
        user: User,  # 도메인 객체, 엔티티가 아님을 주의
    ) -> int:
        return await self.save(session, user)
      
    ...

 

'SQLAlchemy' 카테고리의 다른 글

DTO, 객체 인스턴스 생성  (0) 2024.03.26
2.0 요약 정리  (0) 2024.02.19