일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- frontend
- test
- 티스토리챌린지
- java
- javascript
- backend
- Redux
- JavaSpring
- tanstackquery
- golang
- 웹애플리케이션서버
- typescript
- Spring
- go
- satisfiles
- RTK
- React
- Chakra
- component
- react-hook-form
- css
- designpatterns
- springboot
- storybook
- Gin
- hook
- JPA
- ReactHooks
- 오블완
- Today
- Total
bkdragon's log
[gin] Paging Repository 본문
paging 이 추가된 API를 만들어보려고 한다. gin Clean Architecture 에서 사용하는 기본 CRUD repository 처럼 Paging respository 를 만들고 필요한 도메인에 임베드(상속)로 추가할 수 있게 만들 것이다.
우선 인터페이스를 정의해준다.
type IRepository[M any, ID any] interface {
List() ([]*M, error)
Retrieve(id ID) (*M, error)
Save(entity *M) (*M, error)
Update(id ID, updates map[string]interface{}) (*M, error)
Delete(id ID) error
}
type IPagingRepository[M any, ID any] interface {
ListWithPaging(page int, page_size int) ([]*M, int64 ,error)
}
위에는 원래 있던 CRUD 용이고 IPagingRepository 인터페이스를 추가했다.
이제 인터페이스를 만족하는 구조체를 만들자.
type PagingDataBase[M any, ID any] struct {
pagingdb *gorm.DB
}
func (r *PagingDataBase[M, ID]) ListWithPaging(page int, page_size int) ([]*M, int64 ,error) {
var entities []*M
var count int64
err := r.pagingdb.Model(&entities).Count(&count).Error
if err != nil {
return nil, 0, err
}
offset := (page - 1) * page_size
err = r.pagingdb.Offset(offset).Limit(page_size).Find(&entities).Error
if err != nil {
return nil, 0 ,err
}
return entities,count, nil
}
전체 row의 개수는 Count를 통해 찾을 수 있다.
Offset과 Limit를 이용해서 페이징을 구현할 수 있다.Offset은 특정 인덱스 부터 데이터를 조회하고 Limit는 최대 엔티티 수를 의미한다.
Offset이 10 이면 11번째 부터 조회한다. 예를 들어 page가 2고 size가 10이면 Offset이 10이 된다.
이제 이 인터페이스와 구조체를 추가하고 싶은 도메인의 레포지토리에 임베드 하면 된다. (예시는 기존에 작성하던 UserRepository)
type IUserRepository interface {
IRepository[models.User, int]
IPagingRepository[models.User, int]
FindByEmail(email string) (*models.User, error)
}
type UserRepository struct {
DataBase[models.User, int]
PagingDataBase[models.User, int]
}
이 코드들을 활용하여 기본 CRUD와 Paging 까지 바로 추가할 수 있게 되었다.
Paging에 특정 조건으로 필터링까지하는 API 가 필요하면 어떻게 하면 될까?
새로운 메서드를 추가하면 된다. (IRepository, IPagingRepository 의 역할은 간단한 부분만 자동화 한다고 생각하면 된다. 복잡한 건 직접 구현!)
FilteredUsersWithPaging 이라는 메서드를 추가하고 구현해준다.
type IUserRepository interface {
IRepository[models.User, int]
IPagingRepository[models.User, int]
FindByEmail(email string) (*models.User, error)
FilteredUsersWithPaging(name string, page int, pageSize int) ([]*models.User, int64 ,error)
}
func (r *UserRepository) FilteredUsersWithPaging(name string, page int, pageSize int)([]*models.User, int64 ,error) {
var users []*models.User
var count int64
query := r.pagingdb.Model(&users)
if name != "" {
query = query.Where("name LIKE ?", "%"+name+"%")
}
err := query.Count(&count).Error
if err != nil {
return nil, 0, err
}
offset := (page - 1) * pageSize
err = query.Offset(offset).Limit(pageSize).Find(&users).Error
if err != nil {
return nil, 0 ,err
}
return users,count, nil
}
ListWithPaging 와 거의 비슷하다. Where 절이 추가되었다.
다음엔 정렬을 유연하게 할 수 있는 걸 추가해봐야겠다.
'golang' 카테고리의 다른 글
[gin] Clean Architecture (1) | 2024.09.20 |
---|---|
[gorm] 다형성 관계 (0) | 2024.09.11 |
[go] http 통신 과정 (0) | 2024.09.10 |
[gin] JSON (1) | 2024.09.08 |
[gin] ShouldBindJSON (0) | 2024.09.08 |