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
- Fungsi
Save()
digunakan untuk menyimpan data article ke dalam tabel pada database - Fungsi
Update()
digunakan untuk mengubah data article - Fungsi
Delete()
digunakan untuk menghapus data article - Fungsi
FindById()
digunakan untuk mencari data berdasarkan Id - 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.