pemrograman

05 Membuat Repository Sebagai Data Akses

Pada kali ini kita akan membuat Article Repository yang kebutuhannya untuk komunikasi ke dalam database MySQL. Kita memiliki tabel pada MySQL pada sebelumnya sudah kita jelaskan, lalu kita akan membuat fungsi-fungsi yang nantinya akan digunakan untuk kebutuhan spesifikasi API. Berikut ini fungsi yang akan kita seperti ini

  1. Fungsi Save() digunakan untuk menyimpan data article ke dalam tabel pada database
  2. Fungsi Update() digunakan untuk mengubah data article
  3. Fungsi Delete() digunakan untuk menghapus data article
  4. Fungsi FindById() digunakan untuk mencari data berdasarkan Id
  5. Fungsi GetAll() digunakan untuk mengambil data keseluruhan dari tabel pada database

Fungsi-fungsi tersebut kita simpan dalam satu file article_repository.go dengan menggunakan type interface sebagai kontrak yang nantinya kita implementasikan ditiap masing-masing fungsi.

Pertama buat file article_repository.go pada folder repository lalu isi file tersebut dengan kode dibawah ini.

package repository

import (
	"context"

	"github.com/santekno/learn-golang-restful/models"
)

type ArticleRepository interface {
	GetAll(ctx context.Context) ([]*models.Article, error)
	GetByID(ctx context.Context, id int64) (*models.Article, error)
	Update(ctx context.Context, article *models.Article) (*models.Article, error)
	Store(ctx context.Context, article *models.Article) (int64, error)
	Delete(ctx context.Context, id int64) (bool, error)
}

Interface ini akan menjadi atribute utama dan yang akan diinject pada usecase layer. Usecase nantinya hanya mengetahui fungsi di repository melalui interface ini, sehingga repository harus implement interface ini.

Selanjutnya kita akan membuat satu persatu fungsi yang sudah kita definisikan ini menjadi fungsi implementasi yang akan kita pisah file-nya.

Buat file pada folder repository mysql/article.go lalu isi inisialisasi kode seperti ini

type ArticleStore struct {
	db *sql.DB
}

// New will create an object that represent the article_repository interface
func New(conn *sql.DB) *ArticleStore {
	return &ArticleStore{conn}
}

Struct diatas kita butuhkan untuk mengirimkan koneksi database yang akan kita gunakan untuk melakukan pengolahan data misalkan mengambil, menambah, mengubah dan menghapus data article di dalam table pada database. Inisialisasi struct tersebut akan dipanggil oleh setiap fungsi untuk kebutuhan pengolahan.

Membuat Fungsi Ambil Semua Data Article

Berikut ini fungsi untuk mengambil data article secara keseluruhan seperti dibawah ini.

func (r *ArticleStore) GetAll(ctx context.Context) ([]*models.Article, error) {
	var result []*models.Article

	rows, err := r.db.QueryContext(ctx, queryGetAll)
	if err != nil {
		return result, err
	}

	defer rows.Close()

	for rows.Next() {
		t := models.Article{}
		err = rows.Scan(&t.ID, &t.Title, &t.Content, &t.CreateAt, &t.UpdateAt)

		if err != nil {
			return nil, err
		}

		result = append(result, &t)
	}

	return result, nil
}

Fungsi ini membutuhkan query mengambil data ke dalam database, pada kode diatas memanggil variabel queryGetAll yang berisi query seperti ini.

const queryGetAll = `SELECT id, title, content, create_at, update_at FROM articles`

Pada fungsi ini kita memanggil QueryContext yang mana fungsi tersebut merupakan library dari database/sql yang bisa kita gunakan untuk melakukan pengambilan data berdasarkan query yang sudah di definisikan.

Membuat Fungsi Mengambil Data berdasarkan Id Article

Fungsi untuk mengambil data berdasarkan Id bisa kita lihat seperti ini.

func (r *ArticleStore) GetByID(ctx context.Context, id int64) (*models.Article, error) {
	var result models.Article

	err := r.db.QueryRowContext(ctx, queryGetById, id).Scan(&result.ID, &result.Title, &result.Content, &result.CreateAt, &result.UpdateAt)
	if err != nil {
		return &result, err
	}

	return &result, nil
}

Dengan query yang digunakan queryGetById seperti ini.

const queryGetById = `SELECT id, title, content, create_at, update_at FROM articles WHERE id=?`

Pada query berdasarkan Id ini kita menggunakan fungsi QueryRowContext pada libary database/sql yang mana perbedaannya dari QueryContext yaitu hasil dari pengembalian datanya, jika kita menggunakan QueryContext maka data yang dihasilkan akan berupa rows yang lebih dari satu sehingga perlu kita lakukan perulangan karena banyaknya data yang dikembalikan. Sedangkan untuk QueryRowContext data yang dikembalikan hanya satu data saja yang mana bisa lngsung kita input di dalam struct article.

Membuat Fungsi Mengubah Data Article

Fungsi mengubah data untuk article ini bisa dilihat seperti ini.

func (r *ArticleStore) Update(ctx context.Context, article *models.Article) (*models.Article, error) {
	res, err := r.db.ExecContext(ctx, queryUpdate, article.Title, article.Content, article.UpdateAt, article.ID)
	if err != nil {
		return nil, err
	}

	count, err := res.RowsAffected()
	if err != nil {
		return nil, err
	}

	fmt.Printf("success update with affected %d", count)
	return article, nil
}

Dengan menggunakan query UPDATE sql kita bisa mengubah beberapa kolom yang ada didatabase dengan parameter Id tertentu.

const queryUpdate = `UPDATE article SET nim=?, name=?, birth_place=? WHERE id=?`

Membuat Fungsi Hapus Data Article

Berikut fungsi hapus data article seperti ini.

func (r *ArticleStore) Store(ctx context.Context, article *models.Article) (int64, error) {
	res, err := r.db.ExecContext(ctx, queryInsert, article.Title, article.Content, article.CreateAt, article.UpdateAt)
	if err != nil {
		return 0, err
	}

	lastId, err := res.LastInsertId()
	if err != nil {
		return 0, err
	}

	fmt.Printf("success create with lastId: %d", lastId)
	return lastId, nil
}

func (r *ArticleStore) Delete(ctx context.Context, id int64) (bool, error) {
	_, err := r.db.ExecContext(ctx, queryDelete, id)
	if err != nil {
		return false, err
	}

	return true, nil
}

Dengan query DELETE sql kita bisa menghapus data dalam tabel

const queryDelete = `DELETE FROM article WHERE id=?`

Membuat Fungsi Menambah Data Article

Fungsi untuk menambahkan data article bisa kita buat seperti ini.

func (r *ArticleStore) Store(ctx context.Context, article *models.Article) (int64, error) {
	res, err := r.db.ExecContext(ctx, queryInsert, article.Title, article.Content, article.CreateAt)
	if err != nil {
		return 0, err
	}

	lastId, err := res.LastInsertId()
	if err != nil {
		return 0, err
	}

	fmt.Printf("success create with lastId: %d", lastId)
	return lastId, nil
}

Dengan menggunakan query INSERT kita bisa menambahkan data ke dalam tabel article.

const queryInsert = `INSERT INTO articles(title, content, create_at, update_at) VALUES(?,?,?,?)`

Jika kita lihat untuk menambahkan, mengubah dan menghapus data fungsi pada library database/sql yang digunakan adalah ExecContext. Fungsi ini kita gunakan ketika ada kebutuhan berupa DML atau ketika ada perubahan data.

comments powered by Disqus