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