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 |