Skip to main content

Repository Overview

Pengenalan Repository Pattern dalam API Gateway.

What is Repository Pattern?

Repository Pattern adalah design pattern yang memisahkan logika akses data dari business logic. Ini memberikan:

  • Abstraksi - Business logic tidak perlu tahu detail implementasi database
  • Testability - Mudah di-mock untuk unit testing
  • Maintainability - Perubahan database hanya di satu tempat
  • Reusability - Query yang sama dapat digunakan di banyak tempat

Architecture

┌─────────────┐     ┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│ Controller │────▶│ Repository │────▶│ GORM │────▶│ PostgreSQL │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
│ │
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ DTO │ │ Model │
└─────────────┘ └─────────────┘

Repository Files

FileDeskripsi
sql_repo.goGeneric SQL operations (CRUD, pagination, filtering)
auth_repo.goAuthentication-specific operations
pengguna_repo.goPengguna-specific operations
error_repo.goCustom error handling

Generic vs Specific Repository

Generic Repository (sql_repo.go)

Functions yang dapat digunakan untuk semua model:

// Works with any model
repository.Save(&user)
repository.Save(&product)
repository.GetById(&user, id)
repository.GetById(&product, id)

Specific Repository (auth_repo.go, pengguna_repo.go)

Functions khusus untuk domain tertentu:

// Only for Pengguna
repository.GetByNoPegawai(&pengguna, noPegawai)
repository.GetPagedPengguna(sort, filter, page, perPage)

Key Features

1. Soft Delete

Semua query otomatis exclude data yang is_deleted = true:

db = db.Where("is_deleted = ?", false)

2. Pagination

Built-in pagination support:

data, totalCount, totalPages, err := repository.GetNew(
&model,
sort,
filter,
page,
perPage,
)

3. Filtering

Dynamic filtering dengan operator support:

filter := "[nama,ilike,%john%;status,=,active]"
data, _, _, _ := repository.GetNew(&users, "", filter, 1, 10)

4. Sorting

Dynamic sorting:

sort := "created_at,desc"
data, _, _, _ := repository.GetNew(&users, sort, "", 1, 10)

Usage Example

In Controller

func GetUsers(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
perPage, _ := strconv.Atoi(c.DefaultQuery("perPage", "10"))
sort := c.Query("sort")
filter := c.Query("filter")

var users []models.User
data, totalCount, totalPages, err := repository.GetNew(
&users,
sort,
filter,
page,
perPage,
)

if err != nil {
helpers.SendError(c, helpers.NewInternalError("Failed to fetch users"))
return
}

c.JSON(http.StatusOK, helpers.ResponseData[[]models.User]{
Code: 200,
Status: true,
Message: "Success",
Info: helpers.Info{
Page: page,
PerPage: perPage,
TotalPages: totalPages,
TotalData: totalCount,
},
Data: data.([]models.User),
})
}

Best Practices

  1. Gunakan Generic Repository untuk operasi CRUD standar
  2. Buat Specific Repository untuk query kompleks atau domain-specific
  3. Selalu Handle Error dari repository
  4. Gunakan Transactions untuk operasi multiple
  5. Log Query di development untuk debugging