Aplikasi Persediaan Barang (Sistem Inventory) Menggunakan Yii2 – Part #4

Aplikasi Persediaan Barang (Sistem Inventory) Menggunakan Yii2 - Transaksi Master Detail

Code Factory Sistem Inventory atau Aplikasi Persediaan Barang adalah salah satu aplikasi yang umum dan cukup menantang terutama bagi para programmer pemula yang sedang mengasah skill programming-nya. Artikel ini merupakan lanjutan dari artikel ketiga yang membahas Pembuatan Form Master Barang. Artikel ini akan melanjutkan pembuatan form transaksi dengan desain master-detail menggunakan bantun extension dynamic-form, dan kita buat sederhana saja sehingga akan cukup mudah dipahami para programmer pemula.

Extension Tambahan

Untuk memudahkan kita membangun user interface yang cukup nyaman maka kita memerlukan dua buah extension tambahan, yaitu datepicker untuk memilih tanggal, dan dynamic-form untuk form CRUD master-detail. Gunakan perintah composer berikut ini untuk instalasi-nya.

composer require kartik-v/yii2-widget-datepicker "*"
composer require wbraganca/yii2-dynamicform "*"

[collapsed title=Instalasi Extension]Sistem Inventory atau Aplikasi Persediaan Barang Menggunakan Yii Yii2 PHP Instalasi Extension

Sistem Inventory atau Aplikasi Persediaan Barang Menggunakan Yii Yii2 PHP Instalasi Extension[/collapsed]

Generate CRUD Menggunakan Gii

Silakan generate CRUD untuk Table Transactions dan TransactionDetails dengan cara yang sama seperti saat membuat form master barang.

[collapsed title=Generate CRUD Transactions] Sistem Inventory atau Aplikasi Persediaan Barang Menggunakan Yii Yii2 PHP Generate CRUD Transactions Sistem Inventory atau Aplikasi Persediaan Barang Menggunakan Yii Yii2 PHP Generate CRUD Transactions Sistem Inventory atau Aplikasi Persediaan Barang Menggunakan Yii Yii2 PHP Generate CRUD Transactions [/collapsed] [collapsed title=Generate CRUD TransactionDetails] Sistem Inventory atau Aplikasi Persediaan Barang Menggunakan Yii Yii2 PHP Generate CRUD TransactionDetails Sistem Inventory atau Aplikasi Persediaan Barang Menggunakan Yii Yii2 PHP Generate CRUD TransactionDetails Sistem Inventory atau Aplikasi Persediaan Barang Menggunakan Yii Yii2 PHP Generate CRUD TransactionDetails [/collapsed]

Modifikasi List Transaksi Barang

Hasil generate CRUD dari Yii sangat membantu kita mempercepat proses pengerjaan aplikasi ini, namun masih perlu beberapa penyesuaian dari code standard Gii yang dihasilkan,

'columns' => [
    ['class' => 'yii\grid\SerialColumn'],
    'id',
    'trans_code',
    'trans_date',
    'type_id',
    'remarks',
    ['class' => 'yii\grid\ActionColumn'],
],

Kita dapat menghapus field id yang hanya field identity sehingga tidak penting untuk ditampilkan. Kita juga dapat mengubah field type_id menjadi type.name agar data yang ditampilkan adalah nama jenis transaksinya dan bukan angka id-nya sehingga hasilnya menjadi seperti di bawah ini

'columns' => [
    ['class' => 'yii\grid\SerialColumn'],
    'trans_code',
    'trans_date',
    'type.name',
    'remarks',
    ['class' => 'yii\grid\ActionColumn'],
],

[collapsed title=GridView Transaksi]Sistem Inventory atau Aplikasi Persediaan Barang Menggunakan Yii Yii2 PHP GridView Transaksi tanpa Filter Dropdown[/collapsed]

Hasilnya cukup user-friendly. Namun sayangnya dengan cara di atas, kita tidak bisa melakukan filter terhadap jenis transaksi. Oleh karena itu kita perlu melakukan perubahan agar filter terhadap jenis transaksi barang kita kita lakukan, filter menggunakan dropdown list. Pertama yang kita lakukan adalah mengambil data semua jenis transaksi yang ada di dalam database menggunakan code berikut,

$typeList = ArrayHelper::map(TransactionTypes::find()->asArray()->all(), 'id', 'name');

Kemudian ubah setting column type.name di GridView dengan menambahkan atribut setting filter dan value barupa Closure yang bentuknya spesifik untuk GridView, sehingga menjadi seperti di bawah ini

'columns' => [
    ['class' => 'yii\grid\SerialColumn'],
    'trans_code',
    'trans_date',
    [   'attribute' => 'type_id', 
        'filter' => $typeList, 
        'label' => 'Transaction Type', 
        'value' => function ($model, $index, $widget) { return $model->type->name; }
    ],
    'remarks',
    ['class' => 'yii\grid\ActionColumn'],
],

[collapsed title=GridView Transaksi dengan Filter Dropdown]Sistem Inventory atau Aplikasi Persediaan Barang Menggunakan Yii Yii2 PHP GridView Transaksi dengan Filter Dropdown[/collapsed]

Modifikasi Form Transaksi Barang

Form input transaksi barang melibatkan dua buah table yaitu transactions dan transaction_details sehingga kita memerlukan extension dynamic-form untuk membuatnya. Instalasi dengan menggunakan perintah composer di bawah ini.

composer require wbraganca/yii2-dynamicform "*"

Yang perlu kita lakukan kemudian adalah

  • Membuat class Model untuk memudahkan kita membuat beberapa row TransactionDetails dalam satu baris code saja.
  • Modifikasi ActionCreate di TransactionController untuk proses pembuatan transaksi baru
  • Modifikasi ActionUpdate di TransactionController untuk proses pembuatan transaksi yang sudah ada di database
  • Modifikasi ActionDelete di TransactionController untuk proses penghapusan transaksi
  • Modifikasi form untuk Create dan Update.

Class Model

Class Model ini merupakan turunan dari class yii\base\Model namun kita menambahkan sebuah function createMultiple untuk memudahkan kita membuat beberapa row TransactionDetails berdasarkan isi dari variable POST menggunakan satu baris code saja. 

[collapsed title=Class Model]

namespace app\models;

use Yii;
use yii\helpers\ArrayHelper;

class Model extends \yii\base\Model
{
    /**
     * Creates and populates a set of models.
     * @param string $modelClass
     * @param array $multipleModels
     * @return array
     */
    public static function createMultiple($modelClass, $multipleModels = [])
    {
        $model    = new $modelClass;
        $formName = $model->formName();
        $post     = Yii::$app->request->post($formName);
        $models   = [];

        if (! empty($multipleModels)) {
            $keys = array_keys(ArrayHelper::map($multipleModels, 'id', 'id'));
            $multipleModels = array_combine($keys, $multipleModels);
        }

        if ($post && is_array($post)) {
            foreach ($post as $i => $item) {
                if (isset($item['id']) && !empty($item['id']) && isset($multipleModels[$item['id']])) {
                    $models[] = $multipleModels[$item['id']];
                } else {
                    $models[] = new $modelClass;
                }
            }
        }

        unset($model, $formName, $post);
        return $models;
    }
}

[/collapsed]

Modifikasi ActionCreate

Saat melakukan proses penyimpanan data transaksi baru ke database, kita mengikuti algoritma berikut ini,

  • Load master record
  • Load semua detail records
  • Assign foreign key field di detail records
  • Validate master record
  • Validate detail record
  • Jika validasi berhasil
    • Mulai transaksi database
    • Simpan master record
    • Simpan detail record satu-persatu
    • Jika berhasil semua, commit
    • Jika gagal rollback
    • Tampilkan hasilnya

[collapsed title=ActionCreate]

/**
 * Creates a new Transactions model.
 * If creation is successful, the browser will be redirected to the 'view' page.
 * @return mixed
 */
public function actionCreate()
{
    $model = new Transactions();
    $details = [ new TransactionDetails ];

    // proses isi post variable 
    if ($model->load(Yii::$app->request->post())) {
        $details = Model::createMultiple(TransactionDetails::classname());
        Model::loadMultiple($details, Yii::$app->request->post());

        // assign default transaction_id
        foreach ($details as $detail) {
            $detail->trans_id = 0;
        }

        // ajax validation
        if (Yii::$app->request->isAjax) {
            Yii::$app->response->format = Response::FORMAT_JSON;
            return ArrayHelper::merge(
                ActiveForm::validateMultiple($details),
                ActiveForm::validate($model)
            );
        }

        // validate all models
        $valid1 = $model->validate();
        $valid2 = Model::validateMultiple($details);
        $valid = $valid1 && $valid2;

        // jika valid, mulai proses penyimpanan
        if ($valid) {
            // mulai database transaction
            $transaction = \Yii::$app->db->beginTransaction();
            try {
                // simpan master record                   
                if ($flag = $model->save(false)) {
                    // kemudian simpan detail records
                    foreach ($details as $detail) {
                        $detail->trans_id = $model->id;
                        if (! ($flag = $detail->save(false))) {
                            $transaction->rollBack();
                            break;
                        }
                    }
                }
                if ($flag) {
                    // sukses, commit database transaction
                    // kemudian tampilkan hasilnya
                    $transaction->commit();
                    return $this->redirect(['view', 'id' => $model->id]);
                } else {
                    return $this->render('create', [
                        'model' => $model,
                        'details' => $details,
                    ]);
                }
            } catch (Exception $e) {
                // penyimpanan galga, rollback database transaction
                $transaction->rollBack();
                throw $e;
            }
        } else {
            return $this->render('create', [
                'model' => $model,
                'details' => $details,
                'error' => 'valid1: '.print_r($valid1,true).' - valid2: '.print_r($valid2,true),
            ]);
        }

    } else {
        // inisialisai id 
        // diperlukan untuk form master-detail
        $model->id = 0;
        // render view
        return $this->render('create', [
            'model' => $model,
            'details' => $details,
        ]);
    }
}

[/collapsed]

Modifikasi ActionUpdate

Saat melakukan proses penyimpanan perubahan data transaksi ke database. Agak sedikit berbeda dengan proses pyimpanan transaksi baru, untuk proses edit, kita menghapus semua detail record yang sudah ada sebelumnya di database dan kemudian melakukan insert ulang sebagai record baru. Algoritma-nya adalah seperti berikut ini,

  • Load master record
  • Load semua detail records
  • Assign foreign key field di detail records
  • Validate master record
  • Validate detail record
  • Jika validasi berhasil
    • Mulai transaksi database
    • Simpan master record
    • Delete semua detail record yang sudah ada di database
    • Simpan detail record satu-persatu
    • Jika berhasil semua, commit
    • Jika gagal rollback
    • Tampilkan hasilnya

[collapsed title=ActionUpdate]

/**
 * Updates an existing Transactions model.
 * If update is successful, the browser will be redirected to the 'view' page.
 * @param integer $id
 * @return mixed
 */
public function actionUpdate($id)
{
    $model = $this->findModel($id);
    $details = $model->transactionDetails;

    if ($model->load(Yii::$app->request->post())) {

        $oldIDs = ArrayHelper::map($details, 'id', 'id');
        $details = Model::createMultiple(TransactionDetails::classname(), $details);
        Model::loadMultiple($details, Yii::$app->request->post());
        $deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($details, 'id', 'id')));

        // assign default transaction_id
        foreach ($details as $detail) {
            $detail->trans_id = $model->id;
        }

        // ajax validation
        if (Yii::$app->request->isAjax) {
            Yii::$app->response->format = Response::FORMAT_JSON;
            return ArrayHelper::merge(
                ActiveForm::validateMultiple($details),
                ActiveForm::validate($model)
            );
        }

        // validate all models
        $valid1 = $model->validate();
        $valid2 = Model::validateMultiple($details);
        $valid = $valid1 && $valid2;

        // jika valid, mulai proses penyimpanan
        if ($valid) {
            // mulai database transaction
            $transaction = \Yii::$app->db->beginTransaction();
            try {
                // simpan master record                   
                if ($flag = $model->save(false)) {
                    // delete dahulu semua record yang ada
                    if (! empty($deletedIDs)) {
                        TransactionDetails::deleteAll(['id' => $deletedIDs]);
                    }
                    // kemudian, simpan details record
                    foreach ($details as $detail) {
                        $detail->trans_id = $model->id;
                        if (! ($flag = $detail->save(false))) {
                            $transaction->rollBack();
                            break;
                        }
                    }
                }
                if ($flag) {
                    // sukses, commit database transaction
                    // kemudian tampilkan hasilnya
                    $transaction->commit();
                    return $this->redirect(['view', 'id' => $model->id]);
                }
            } catch (Exception $e) {
                // penyimpanan galga, rollback database transaction
                $transaction->rollBack();
                throw $e;
            }
        } else {
            return $this->render('create', [
                'model' => $model,
                'details' => $details,
                'error' => 'valid1: '.print_r($valid1,true).' - valid2: '.print_r($valid2,true),
            ]);
        }
    }

    // render view
    return $this->render('update', [
        'model' => $model,
        'details' => (empty($details)) ? [new TransactionDetails] : $details
    ]);
}

[/collapsed]

Modifikasi ActionDelete

Pada saat menghapus data transaksi maka yang perlu kita lakukan adalah terlebih dahulu menghapus detail record sebelum menghapus master/parent record. Algoritma-nya adalah sebagai berikut

  • Mulai transaksi database
  • Delete semua detail record satu-persatu
  • Delete master record
  • Jika berhasil semua, commit
  • Jika gagal rollback
  • Tampilkan index transaksi barang

[collapsed title=ActionDelete]

/**
 * Deletes an existing Transactions model.
 * If deletion is successful, the browser will be redirected to the 'index' page.
 * @param integer $id
 * @return mixed
 */
public function actionDelete($id)
{
    $model = $this->findModel($id);
    $details = $model->transactionDetails;

    // mulai database transaction
    $transaction = \Yii::$app->db->beginTransaction();
    try {
        // pertama, delete semua detail records
        foreach ($details as $detail) {
            $detail->delete();
        }
        // kemudian, delete master record
        $model->delete();
        // sukses, commit transaction
        $transaction->commit();

    } catch (Exception $e) {
        // gagal, rollback database transaction
        $transaction->rollBack();
    }

    return $this->redirect(['index']);
}

[/collapsed]

Modifikasi create.php

โ€‹Kita perlu menambahkan variable $details agar dapat dikenali di dalam _form.php

โ€‹    <?= $this->render('_form', [
        'model' => $model,
        'details' => $details,
    ]) ?>

Modifikasi update.php

โ€‹Kita juga perlu menambahkan variable $details agar dapat dikenali di dalam _form.php

    <?= $this->render('_form', [
        'model' => $model,
        'details' => $details,
    ]) ?>

Modifikasi _form.php

โ€‹Code lengkapnya adalah seperti berikut ini

[collapsed title=Code HTML form transaksi]

<div class="transactions-form">

    <?php $form = ActiveForm::begin(['id' => 'transactions-form']); ?>

    <div class="row">
        <div class="col-sm-4 col-md-6">
		    <?= $form->field($model, 'trans_code')->textInput(['maxlength' => true]) ?>
        </div>
        <div class="col-sm-4 col-md-3">
		    <?php 
				echo '<label class="control-label" for="transactions-trans_date">Transaction Date</label>';
				echo DatePicker::widget([
					'id' => 'transactions-trans_date',
				    'name' => 'Transactions[trans_date]',
				    'type' => DatePicker::TYPE_COMPONENT_APPEND,
				    'value' => date('Y-m-d'),
				    'pluginOptions' => [
				        'autoclose'=>true,
				        'format' => 'yyyy-mm-dd'
				    ]
				]);
		    ?>
        </div>
        <div class="col-sm-4 col-md-3">
		    <?= $form->field($model, 'type_id')->dropDownList(
		        ArrayHelper::map(TransactionTypes::find()->all(), 'id', 'name'),  
		        ['prompt'=>'* Pilih Transaksis *']                          
		    ); ?>
        </div>
        <div class="col-sm-12 col-md-12">
		    <?= $form->field($model, 'remarks')->textInput(['maxlength' => true]) ?>
        </div>
    </div><!-- .row -->

    <div class="panel panel-default">
        <div class="panel-heading"><h4><i class="glyphicon glyphicon-th-list"></i> Transaction Details</h4></div>
        <div class="panel-body">
             <?php DynamicFormWidget::begin([
                'widgetContainer' => 'dynamicform_wrapper',  // required: only alphanumeric characters plus "_" [A-Za-z0-9_]
                'widgetBody' => '.container-items',          // required: css class selector
                'widgetItem' => '.item',                     // required: css class
                'limit' => 999,                                // the maximum times, an element can be cloned (default 999)
                'min' => 1,                                  // 0 or 1 (default 1)
                'insertButton' => '.add-item',               // css class
                'deleteButton' => '.remove-item',            // css class
                'model' => $details[0],
                'formId' => 'transactions-form',
                'formFields' => [
                    'trans_id',
                    'item_id',
                    'quantity',
                    'remarks',
                ],
            ]); ?>

            <div class="container-items"><!-- widgetContainer -->
            <?php foreach ($details as $i => $detail): ?>
                <div class="item row">
                    <?php
                        // necessary for update action.
                        if (! $detail->isNewRecord) {
                            echo Html::activeHiddenInput($detail, "[{$i}]id");
                        }
                    ?>
                    <div class="col-sm-8 col-md-4">
					    <?= $form->field($detail, "[{$i}]item_id")->dropDownList(
					        ArrayHelper::map(Items::find()->all(), 'id', 'name'),  // Flat array ('id'=>'label')
					        ['prompt'=>'* Pilih Barang *']                          // options
					    ); ?>
                    </div>
                    <div class="col-sm-4 col-md-2">
                        <?= $form->field($detail, "[{$i}]quantity")->textInput(['maxlength' => true]) ?>
                    </div>
                    <div class="col-sm-10 col-md-5">
                    	<?= $form->field($detail, "[{$i}]remarks")->textInput(['maxlength' => true]) ?>
                    </div>
                    <div class="col-sm-2 col-md-1 item-action">
                    	<div class="pull-right">
	                        <button type="button" class="add-item btn btn-success btn-xs">
	                        	<i class="glyphicon glyphicon-plus"></i></button> 
	                        <button type="button" class="remove-item btn btn-danger btn-xs">
	                        	<i class="glyphicon glyphicon-minus"></i></button>
                    	</div>
                    </div>
                </div><!-- .row -->

            <?php endforeach; ?>
            </div>

            <?php DynamicFormWidget::end(); ?>
        </div>
    </div>


    <div class="form-group">
        <?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
    </div>

    <?php ActiveForm::end(); ?>

</div>

[/collapsed]

[collapsed title=Form Transaksi Barang]Sistem Inventory atau Aplikasi Persediaan Barang Menggunakan Yii Yii2 Form Transaksi Barang Dynamic-Form[/collapsed]

Membuat View Transaksi Barang

Untuk menampilkan data master-detail, maka kita harus record master dan semua record detail yang berelasi, sehingga kita perlu mengubah ActionView menjadi seperti ini

[collapsed title=Code ActionView]

/**
 * Displays a single Transactions model.
 * @param integer $id
 * @return mixed
 */
public function actionView($id)
{
    return $this->render('view', [
        'model' => $this->findModel($id),
        'details' => $this->findDetails($id),
    ]);
}

/**
 * Finds the Transactions model based on its primary key value.
 * If the model is not found, a 404 HTTP exception will be thrown.
 * @param integer $id
 * @return Transactions the loaded model
 * @throws NotFoundHttpException if the model cannot be found
 */
protected function findModel($id)
{
    if (($model = Transactions::findOne($id)) !== null) {
        return $model;
    } else {
        throw new NotFoundHttpException('The requested page does not exist.');
    }
}

/**
 * Finds the TransactionDetails model based on its foreign key value.
 * @param integer $id
 * @return data provider TransactionDetails for GridView 
 */
protected function findDetails($id)
{
    $detailModel = new TransactionDetailsSearch();
    return $detailModel->search(['TransactionDetailsSearch'=>['trans_id'=>$id]]);
}

[/collapsed]

Dan jangan lupa mengubah view.php agar menampilkan data yang didapat dari controller. Kita akan menggunakan DetailView untuk master row, dan menggunakan GridView untuk menampilkan detail row.

[collapsed title=HTML Code View Transaksi]

<?= DetailView::widget([
    'model' => $model,
    'attributes' => [
        'trans_code',
        [
            'attribute' => 'trans_date',
            'format' => [ 'date', 'php: d-M-Y' ],
            'labelColOptions' => [ 'style'=>'width:30%; text-align:right;' ]
        ],
        'type.name',
        'remarks',
    ],
]) ?>

<div class="item panel panel-info">
    <div class="panel-heading">
        <h3 class="panel-title pull-left"><i class="glyphicon glyphicon-barcode"></i> Transaction Line Item</h3>
        <div class="clearfix"></div>
    </div>
    <div class="panel-body">
        <?= GridView::widget([
            'dataProvider' => $details,
            'columns' => [
                ['class' => 'yii\grid\SerialColumn'],

                [
                    'attribute' => 'item_id',
                    'value' => 'item.code',
                    'header' => 'Item Code',
                ],
                [
                    'attribute' => 'item_id',
                    'value' => 'item.name',
                    'header' => 'Item Name',
                ],
                'quantity',
                'remarks',
            ],
        ]); ?>
    </div>
</div>

[/collapsed]

[collapsed title=Penampakan View Transaksi Barang]Sistem Inventory atau Aplikasi Persediaan Barang Menggunakan Yii Yii2 PHP View Transaction[/collapsed]

Simpulan

Mudah-mudahan tutorial ini dapat membantu teman-teman yang sedang belajar membuat aplikasi inventory, khususnya yang menggunakan Yii Framework. Source code aplikasi ini dapat dilihat di GitHub, silakan digunakan untuk keperluan pembelajaran saja.

.

 

Aplikasi Persediaan Barang (Sistem Inventory) Menggunakan Yii2 – Part #3

Aplikasi Persediaan Barang (Sistem Inventory) Menggunakan Yii2 - Master Barang (Items)

Code Factory Sistem Inventory atau Aplikasi Persediaan Barang adalah salah satu aplikasi yang umum dan cukup menantang terutama bagi para programmer pemula yang sedang mengasah skill programming-nya. Artikel kali ini akan membahas pengembangan CRUD untuk master data barang (items) setelah sebelumnya kita membahas persiapan database yang akan kita gunakan dalam Aplikasi Inventory ini. Kita akan memanfaatkan Gii Code Generator untuk mempercepat proses pengembangannya. Aplikasi yang akan kita bangun sederhana saja sehingga akan cukup mudah dipahami para programmer pemula.

(more…)

Aplikasi Persediaan Barang (Sistem Inventory) Menggunakan Yii2 – Part #2

Aplikasi Persediaan Barang (Sistem Inventory) Menggunakan Yii2 - Part #2

Code Factory | Selama proses pengembangan aplikasi database, struktur database yang digunakan juga ikut berubah dan berkembang seperti halnya kode sumber (source code) aplikasi kita. Misalnya, membuat tabel baru, menambahkan kolom baru, menambahkan indeks untuk meningkatkan kinerja query, dan sebagainya. Karena perubahan struktur database sering membutuhkan beberapa perubahan kode sumber, Yii menyediakan fitur migrasi database yang memungkinkan Anda untuk melacak perubahan database, melakukan upgrade struktur database, atau downgrade struktur database jika diperlukan. Referensi lengkap tentang migrasi database di Yii bisa dilihat di laman ini.

(more…)

Aplikasi Persediaan Barang (Sistem Inventory) Menggunakan Yii2 – Part #1

Aplikasi Persediaan Barang (Sistem Inventory) Menggunakan Yii2 - Part #1

Code Factory Sistem Inventory atau Aplikasi Persediaan Barang adalah salah satu aplikasi yang umum dan cukup menantang terutama bagi para programmer pemula yang sedang mengasah skill programming-nya. Aplikasi ini bisa kita buat sangat sederhana dengan hanya melibatkan data barang dan transaksinya, atau dibuat lebih rumit dengan melibatkan data gudang, kategori barang, proses approval, dan sebagainya. Artikel ini akan coba membahas aplikasi persediaan barang menggunakan framework Yii2. Aplikasi yang akan kita bangun sederhana saja agar mudah dipahami para programmer pemula.

Instalasi Apache, PHP, dan MySQL (atau MariaDB)

Yii2 membutuhkan minimal PHP versi 5.4 jadi sebelumnya kita harus pastikan bahwa sudah tersedia PHP 5.4 terinstall di laptop atau komputer kita. Dan karena kita akan membuat aplikasi database, maka pastikan juga laptop kita sudah terinstall database MySQL atau MariaDB. Untuk para pengguna Windows, disarankan menggunakan XAMPP minimal versi 1.8 untuk bisa menjalankan Yii2 ini, sedangkan pengguna Linux bisa menggunakan LAMP bawaan distro masing-masing. 

Instalasi Yii2 Menggunakan Composer

Instalasi Yii2 bisa dilakukan dengan 2 (dua) cara, yaitu menggunakan composer atau zip archive. Kedua cara instalasi tersebut sama mudahnya, namun composer memerlukan koneksi internet untuk berjalan. Untuk aplikasi ini kita akan menggunakan template basic yang lebih sederhana dan simple dibandingkan template advance. Perbedaan template basic dengan advance terletak pada struktur pengelolaan file saja, dan template advance ditujukan untuk project yang lebih kompleks. Dokumentasi Yii2 juga menerangkan langkah demi langkah instalasi template basic di laman ini

Jika composer belum terpasang di laptop silakan kunjungi laman getcomposer.org untuk mendapatkan petunjuk instalasi lengkapnya. Untuk pengguna Linux dan MacOS dapat menggunakan perintah command-line berikut ini:

curl -sS https://getcomposer.org/installer | php
mv composer.phar /usr/local/bin/composer

Sedangkan pengguna Windows dapat mengunduh (download) dan menjalankan Composer-Setup.exe. Silakan pelajari Dokumentasi Composer jika kamu mengalami masalah saat proses instalasi, atau mungkin sekedar ingin tahu lebih jauh tentang composer. 

Jika Composer sudah terpasang, maka jalankan perintah berikut ini untuk measang Yii2 di laptop kita.Pastikan menjalankan perintah ini di dalam folder yang bisa diakses via browser, misalkan di dalam folder htdocs instalasi xampp kamu.

composer global require "fxp/composer-asset-plugin:~1.0"
composer create-project --prefer-dist yiisoft/yii2-app-basic inventory

Perintah pertama tujuannya untuk memasang composer asset plugin yang memudahkan kita mengelola package yang tersedia di Composer. Perimtah ini cukup dilakukan sekali saja saat pertama kali memasang Yii. Sedangkan perintah kedua tujuannya untuk memasang Yii ke dalam folder inventory. Kita bisa mengganti nama folder tujuan menjadi apapun yang kita inginkan.

Note: During the installation Composer may ask for your Github login credentials. This is normal because Composer needs to get enough API rate-limit to retrieve the dependent package information from Github. For more details, please refer to the Composer documentation.

Instalasi Yii2 Menggunakan Zip Archive

Lakukan 3 (tiga) langkah berikut ini jika ingin memasang Yii Framework menggunakan arsip zip:

  1. Unduh (download) file arsip zip dari yiiframework.com.
  2. Extract file arsip yang berhasil diunduh ke dalam folder yang bisa diakses via browser, misalkan ke dalam folder htdocs instalasi xampp kamu..
  3. Buka dan ubah file config/web.php dengan mengubah setting cookieValidationKey, isilah dengan string apapun kesukaanmu (cookieValidationKey secara otomatis terisi jika kita melakukan instalsi menggunakan Composer):

    // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
    'cookieValidationKey' => 'enter your secret key here',

Memastikan Yii sudah terpasang

Untuk memastikan apakan Yii Framework sudah terpasang (installed) maka yang perlu kita lakukan adalah membuka browser. Dengan asumsi bahwa kita menginstall yii ke dalam folder inventory dan mengetikkan alamat berikut ini
http://localhost/inventory/web/

dan seharusnya halaman berikut akan muncul di browser.

Aplikasi Persediaan Barang (Sistem Inventory) Menggunakan Yii2 - Part #1

 

.

Aplikasi Inventory Sederhana – Form Transaksi Barang Masuk

Aplikasi Inventory Sederhana - Form Transaksi Barang Masuk Inventory In

Form Transaksi Barang Masuk | Setelah sebelumnya kita berhasil membuat form entri master barang, berikutnya kita akan membuat form untuk mengelola proses CRUD (Create, Read, Update, Delete) data Transaksi Barang Masuk di Aplikasi Inventory ini. Untuk mengelola data master barang ini, kita memerlukan 2 (dua) buah form, yaitu Form List Transaksi Barang Masuk, dan Form Entri Transaksi Barang Masuk. Sama seperti form untuk mengelola data master barang, kedua form transaksi ini juga akan menggunakan metode data-binding untuk menampilkan data yang berhasil diambil menggunakan library data access layer yang kita buat sebelumnya.

Artikel ini adalah lanjutan dari artikel berseri tentang Tutorial Membuat Aplikasi Inventory Sederhana Menggunakan VB.net dan Database MySQL

Persiapkan Data Access Layer

Form transaksi ini merupakan form master-detail yang melibatkan 2 (dua) buah table, yaitu transactions sebagai master table, dan transaction_details sebagai detail table. Desain dari kedua table ini dapat di lihat dalam artikel ini. Untuk itu kita perlu mendefinisikan relasi foreign key antar DataTable yang ada di dalam DataSet dsInventory. Relasi ini yang nantinya akan sangat membantu kita dalam proses data-binding ke form transaksi.

[collapsed title=Setting Relasi Foreign Key]Pertama-tama bukalah desain DataSet dsInventory, kemudian cari link relasi antara table transactions dengan table transaction_details, setelah itu klik tombol kanan mouse untuk menampilkan context menu seperti gambar di bawah ini.

Persiapkan Data Access Layer Edit Relation Foreign Key

Setelah ini pilihlah menu Edit Relation, dan kemudian ubahlah setting-nya menjadi “Both Relation and Foreign Key Contraints” dan ubah juga setting Update Rule dan Delete Rule menjadi Cascade, seperti tampak pada gambar di bawah ini.

Persiapkan Data Access Layer Edit Relation Foreign Key

[/collapsed] [collapsed title=Setting Query Berdasarkan Jenis Transaksi]

Berikutnya kita tambahkan Query untuk memudahkan proses data retrieval (temu kembali data) di form list transaksi barang masuk, Caranya dengan membuka DataSet dsInventory, kemudian lakukan klik kanan pada table transactions dan pilih menu “Add Query” seperti tampak pada gambar di bawah ini.

Persiapkan Data Access Layer Add Tambah Query By Tipe Jenis Transaksi

Setelah itu berikan nama method sebagai FillByType dan GetDataByType, karena method ini kita gunakan untuk mengambil data berdasarkan tipe atau jenis transaksinya. Hasilnya akan tampak seperti gambar di bawah ini.

Persiapkan Data Access Layer Add Tambah Query By Tipe Jenis Transaksi

[/collapsed]

Desain Form Entri Transaksi Barang Masuk

Berikutnya kita buat desain form transaksi barang masuk. Desain form transaksi ini akan menggunakan Visual Inheritance seperti yang sudah dibahas sebelumnya di artikel desain user interface dan desain form master barang, jadi silakan pelajari kedua artikel tersebut sebelum melanjutkan membaca artikel ini.

[collapsed title=Desain Form Entri Barang Masuk]Silakan buat sebuah Inherited Form dari template form List dan kemudian tambahkan semua kontrol yang diperlukan antara lain 

  • TextBox untuk Kode Transaksi
  • DateTimePicker untuk Tanggal Transaksi
  • Multiline TextBox untuk field Remarks atau Keterangan
  • DataGridView untuk detail transaksi

Tambahkan juga beberapa komponen

  • DataSet DsInventory
  • TransactionsTableAdapter untuk proses retrieval dan saving data di table transactions.
  • Transaction_detailsTableAdapter untuk proses retrieval dan saving data di table transaction_details.
  • ItemsTableAdapter untuk proses retrieval lookup data items

Hasilnya akan tampak seperti gambar di bawah ini.

Desain Form Entri Transaksi Barang Masuk User Inteface Design

Setelah desain form selesai kita buat, lanjutkan dengan setting data-binding pada property Text untuk field Transaction Code seperti tampak pada gambar di bawah ini. Lakukan juga hal yang sama untuk field Transaction Date, Remarks dan DataGridView. Gambar di bawah adalah contoh setting data-binding property Text untuk Transaction Code.

Desain Form Entri Transaksi Barang Masuk User Inteface Design

[/collapsed]

Berikutnya yang perlu kita lakukan adalah mengkonfigurasikan binding DataGridView agar memudahkan kita menambahkan detail barang yang terlibat dalam transaksi bersangkutan. Khusus untuk binding DataGridView, yang kita lakukan adalah setting property DataMember dari DataGridView ke relasi yang sudah kita buat sebelumnya, yaitu transaction_details_ibfk_1, seperti tampak pada gambar di bawah ini.

[collapsed title=Setting DataGridView untuk Master-Detail]

Desain Form Entri Transaksi Barang Masuk User Inteface Design

[/collapsed]

Setelah setting binding kita lakukan, selanjutnya ubah property Visible untuk beberapa kolom yang tidak perlu dilihat oleh user atau pengguna, misalkan kolom id, trans_id, item_code, dan item_name. Caranya adalah dengan melakukan klik kanan mouse di atas DataGridView, kemudian pilih menu “Edit Columns” setelah itu silakan ubah property visible menjadi false, seperti tampak pada gambar di bawah ini.

[collapsed title=Setting DataGridView untuk Master-Detail]

Desain Form Entri Transaksi Barang Masuk User Inteface Design

Desain Form Entri Transaksi Barang Masuk User Inteface Design

[/collapsed]

Untuk memudahkan pengguna memilih barang yang akan masuk dalam transaksi ini, maka kita buatkan sebuah ComboBox berisikan list Items sehingga user dapat langsung memilih dari daftar yang tersedia. Caranya adalah buka menu “Edit Columns” kemudian pilih field item_id dan set ColumnType sebagai ComboBoxColumn, seperti tampak pada gambar di bawah ini.

[collapsed title=Setting ComboBox Items di DataGridView untuk Master-Detail]

Desain Form Entri Transaksi Barang Masuk User Inteface Design

[/collapsed]

Berikutnya kita beritahukan vb.net untuk mengambil data Items dari DataSet DsInventory dengan cara mengkonfigurasikan property DataSource, DisplayMember, dan ValueMember menjadi seperti tampak pada gambar di bawah ini.

[collapsed title=Setting ComboBox Items di DataGridView untuk Master-Detail]

Desain Form Entri Transaksi Barang Masuk User Inteface Design

[/collapsed]

Hasil akhirnya akan tampak seperti pada gambar di bawah ini.

[collapsed title=Setting ComboBox Items di DataGridView untuk Master-Detail]

Desain Form Entri Transaksi Barang Masuk User Inteface Design

[/collapsed]

Kode Sumber Form Entri Transaksi Barang Masuk

Kode sumber untuk proses penyimpanan data dalam model master-detail agak sedikit sulit dikarenakan setelah menyimpan data baru ke master table, kita harus mengambil id auto_increment yang dihasilkan dari database kemudian menyesuaikannya ke data di detail table agar referential integrity tetap terjaga.

[collapsed title=Kode Sumber Constructor] 

Constructur New kita buat dua versi untuk membedakan proses Add atau Edit, karena perlakuannya berbeda pada saat penyimpanan data, asumsinya adalah jika TransID yang diberikan bernilai kurang dari 0 (nol) maka kita anggap menambahkan data baru.

    Public Sub New()
        ' This call is required by the designer.
        InitializeComponent()
        ' panggil inisialisasi database
        InitializeDatabase(-1)
    End Sub

    Public Sub New(TransID As Integer)
        ' This call is required by the designer.
        InitializeComponent()
        ' panggil inisialisasi database
        InitializeDatabase(TransID)
    End Sub

[/collapsed]

[collapsed title=Kode Sumber Inisialisasi Database] 

Inisialisasi database membedakan proses add new dan edit data seperti tampak pada potongan kode berikut ini.

    Private Sub InitializeDatabase(TransID As Integer)
        ' load lookup/reference table
        Me.ItemsTableAdapter.Fill(Me.DsInventory.items)
        ' try retrieve data
        Try
            ' periksa nilai ItemID
            ' jika kurang dari 0 maka kita asumsikan mau bikin data baru
            ' jika lebih dari 0 maka kita asumsikan ambil bikin data lama
            If TransID < 0 Then
                IsNewData = True
                ' tambahkan row baru
                Me.BindingContext(Me.DsInventory.transactions).AddNew()
                ' nilai default untuk beberapa field
                Dim NewID As String = Helper.GenerateNewID(TransCode)
                Dim dv As DataRowView = Me.BindingContext(Me.DsInventory.transactions).Current
                dv("type_id") = 1 ' IN: barang masuk
                dv("trans_code") = NewID
                dv("trans_date") = DateTime.Today
                TextBox1.Text = NewID
                DateTimePicker1.Value = DateTime.Today
            Else
                IsNewData = False
                ' retrieve data dari database
                Me.TransactionsTableAdapter.FillByID(Me.DsInventory.transactions, TransID)
                Me.Transaction_detailsTableAdapter.FillByTransID(Me.DsInventory.transaction_details, TransID)
            End If
        Catch ex As Exception
            MessageBox.Show("Error retrieving data from database\nDetails: " + ex.Message,
                Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        End Try
    End Sub

[/collapsed]

[collapsed title=Kode Sumber Simpan Data] 

Proses penyimpanan data melibatkan dua table seperti pada potongan kode di bawah ini, silakan perhatikan komentar pada tiap baris kode yang menjelaskan maksud dari masing-masing baris kode yang ada.

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ' try saving data
        Try
            ' akhiri proses editing
            Me.BindingContext(Me.DsInventory.transactions).EndCurrentEdit()
            Me.BindingContext(Me.DsInventory.transaction_details).EndCurrentEdit()
            ' cek apakah add new atau edit data
            If (IsNewData) Then
                Dim dsChanges As New dsInventory
                ' copy master record dari main dataset
                ' harus dilakukan krena main dataset sebelumnya sudah 
                ' AcceptChanges padahal belum diupdate ke database 
                dsChanges.transactions.Rows.Add(Me.DsInventory.transactions(0).ItemArray)
                ' copy juga detail record dari main dataset
                For i = 0 To Me.DsInventory.transaction_details.Rows.Count - 1
                    dsChanges.transaction_details.Rows.Add(Me.DsInventory.transaction_details(i).ItemArray)
                Next

                ' simpan perubahan ke master table
                Me.TransactionsTableAdapter.Update(dsChanges.transactions)

                ' retrieve generated identity field
                Dim id As Long = 0
                Dim sql As String = "select last_insert_id()"
                Using cn As New MySqlConnection(My.Settings.inventoryConnectionString)
                    Using cm As New MySqlCommand(sql, cn)
                        cn.Open()
                        id = cm.ExecuteScalar
                        cn.Close()
                    End Using
                End Using

                ' assign retrieved id to master table
                dsChanges.transactions(0).id = id
                dsChanges.transactions.AcceptChanges()
                ' simpan perubahan ke details table
                Me.Transaction_detailsTableAdapter.Update(dsChanges.transaction_details)

            Else
                ' simpan perubahan ke database
                Me.TransactionsTableAdapter.Update(Me.DsInventory.transactions)
                Me.Transaction_detailsTableAdapter.Update(Me.DsInventory.transaction_details)
            End If
            ' informasikan data berhasil disimpan
            MessageBox.Show("Data BERHASIL disimpan!",
                Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information)
            ' tutup form
            Me.Close()
        Catch ex As Exception
            MessageBox.Show("Error saving data to database " + vbCrLf + "Details: " + ex.Message,
                Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        End Try
    End Sub

[/collapsed]

Desain Form List Transaksi Barang Masuk

Berikutnya kita buat desain form list transaksi barang masuk. Desain form list transaksi ini juga akan menggunakan Visual Inheritance seperti yang sudah dibahas sebelumnya di artikel desain user interface dan cara melakukan setting data-binding untuk grid list transaksi bisa di lihat di artikel desain form master barang, jadi silakan pelajari kedua artikel tersebut sebelum melanjutkan membaca artikel ini.

[collapsed title=Desain Form List Transaksi Barang Masuk] 

Desain Form List Transaksi Barang Masuk User Inteface Design

[/collapsed]

Kode Sumber Form List Transaksi Barang Masuk

Secara umum hampir tidak ada perbedaan pada code di artikel sebelumnya, hanya ada penambahan variable TransCode untuk membedakan jenis transaksi yang akan dimuat dari dalam database. Silakan perhatikan dengan seksama komentar yang terdapat dalam baris kode sumber, karena komentar-komentar tersebut menerangkan tujuan dari baris-baris kode yang ada

[collapsed title=Kode Sumber Constructor dan Refresh Data] 

    ' kode jenis transaksi
    Private TransCode As String = "IN"

    Private Sub frmTransactionIn_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ' retrieve data from database
        Me.TransactionsTableAdapter.FillByType(Me.DsInventory.transactions, TransCode)
    End Sub

    Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
        Me.TransactionsTableAdapter.ClearBeforeFill = True
        Me.TransactionsTableAdapter.FillByType(Me.DsInventory.transactions, TransCode)
    End Sub

[/collapsed]

[collapsed title=Kode Sumber Loading Form Entri Data]Perbedaan Add dan Edit data adalah kita melempar parameter id transaksi ke form entri sebagai kondisi kita melakukan edit data

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ' start process
        Cursor = Cursors.AppStarting
        ' prepare variables
        Dim fx As frmTransInEntry
        fx = New frmTransInEntry
        ' tampilkan form
        fx.ShowDialog()
        ' refresh data, ambil data yang berubah
        Button4.PerformClick()
        ' finish process
        Cursor = Cursors.Default
    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        ' start process
        Cursor = Cursors.AppStarting
        ' prepare variables
        Dim id As Integer
        Dim fx As frmTransInEntry
        ' ambil id data yg akan diedit
        id = DataGridView1.SelectedRows(0).Cells("id").Value
        ' create form entry berdasarkan id yang dipilih
        fx = New frmTransInEntry(id)
        ' refresh data, ambil data yang berubah
        Button4.PerformClick()
        ' tampilkan form
        fx.ShowDialog()
        ' finish process
        Cursor = Cursors.Default
    End Sub

[/collapsed]

[collapsed title=Kode Sumber Hapus Data Transaksi] 

    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        ' start process
        Cursor = Cursors.AppStarting
        ' prepare variables
        Dim dr As DialogResult
        Dim id As Integer
        Dim code As String
        Dim name As String
        Dim message As String
        Dim pos As Integer
        ' ambil id dan code dari data yg akan diedit
        Dim dv As DataRowView
        dv = Me.BindingContext(Me.TransactionsBindingSource).Current
        id = Convert.ToInt32(dv("id"))
        code = Convert.ToString(dv("code"))
        name = Convert.ToString(dv("name"))
        ' buat pesan konfirmasi
        message = String.Format("Are you sure to delete this [{0}] {1} data ? ", code, name)
        ' try deleting
        Try
            dr = MessageBox.Show(message,
                Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question)
            If dr = Windows.Forms.DialogResult.Yes Then
                pos = Me.BindingContext(Me.TransactionsBindingSource).Position
                Me.BindingContext(Me.TransactionsBindingSource).RemoveAt(pos)
                Me.TransactionsTableAdapter.Update(Me.DsInventory)
                Me.DsInventory.AcceptChanges()
            End If
        Catch ex As Exception
            MessageBox.Show("Error deleting data from database\nDetails: " + ex.Message,
                Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Me.DsInventory.RejectChanges()
        End Try
        ' finish up
        Cursor = Cursors.Default
    End Sub

[/collapsed]

Simpulan

Jika kita perhatikan kode sumber yang kita tuliskan di aplikasi ini sangat sedikit sekali dikarenakan kita menggunakan metode data-binding. Kita juga tidak perlu lagi repot-repot membuat perintah SQL untuk proses CRUD, karena proses CRUD ini sudah ditangani di data access layer. Dengan makin sedikit-nya kode yang harus kita tuliskan tentunya akan semakin meningkatkan produktifitas kita semua sebagai programmer dan semakin banyak karya-karya fenomenal yang bisa kita buat.

Source Code

Untuk memudahkan teman-teman mempelajari hal ini, silakan Download Source Code Di SiniDibuat menggunakan Visual Studio 2013,  

Salam PojokProgrammer ^_^

 

/

Aplikasi Inventory Sederhana – Form Master Barang

Aplikasi Inventory Sederhana User Interface Antarmuka Pengguna Form Utama Master Barang

Form Master Barang | Setelah sebelumnya kita berhasil membuat templare desain user interface dan data access layer, berikutnya kita akan membuat form untuk mengelola proses CRUD (Create, Read, Update, Delete) untuk data Master Barang di Aplikasi Inventory ini. Untuk mengelola data master barang ini, kita memerlukan 2 (dua) buah form, yaitu Form List Barang, dan Form Entri Barang. Kedua form tersebut akan menggunakan metode data-binding untuk menampilkan data yang berhasil diambil menggunakan library data access layer yang kita buat sebelumnya.

Artikel ini adalah lanjutan dari artikel berseri tentang Tutorial Membuat Aplikasi Inventory Sederhana Menggunakan VB.net dan Database MySQL

Data Binding

Data Binding adalah metode untuk menghubungkan elemen atau komponen user interface dengan data access layer di belakangnya. Dengan konfigurasi yang benar, maka perubahan apapun yang ada di data layer dapat langsung terlihat di user interface. Dan juga sebaliknya, perubahan yang kita lakukan di form user interface dapat langsung terseimpan ke database, hanya dengan memanfaatkan beberapa baris kode saja. Untuk mencapai hal ini, kita hanya perlu mengkonfigurasikan property data-binding yang ada di setiap elemen user interface yang terlibat. Jadi misalkan kita mempunyai sebuah TextBox yang di-binding ke sebuah DataSet, maka ketika kita mengisikan sesuatu, atau mengubah isi TextBox bersangkutan, maka secara otomatis data yang tersimpan di DataSet juga ikut berubah.

Form Entri Barang

Kita akan menggunakan satu buah form yang sama untuk proses menambah data baru (Add New) dan mengubah data lama (Edit) dikarenakan field yang terlibat akan sama, hanya berbeda behavior saat di awal melakukan inisialisasi data. Saat menambah data baru yang perlu dilakukan adalah menambahkan satu row kosong, sedangkan saat mengubah data yang dilakukan adalah mengambil ulang (Retrieve) data dari database. Langkah-langkah yang perlu dilakukan antara lain:

  • Menyiapkan sebuah Inherited Form dari template frmEdit kemudian kita beri nama frmItemEdit. Untuk menambahkan form turunan dari template yang sudah kita buat di atas maka, maka silakan buka Form Dialog Add New Item, dan pilih Inherited Form seperti gambar di bawah ini, kemudian berikan nama form turunan dan klik tombol [Add]

[collapsed title=Spoiler: Add New Item Dialog] Aplikasi Inventory Sederhana Desain User Interface Visual Inheritance BiruniLabs [/collapsed]

  • Berikutnya akan muncul Dialog Box yang meminta kita untuk memilih Form superclass, atau Form template layout yang akan kita pakai sebagai parent, seperti tampak pada gambar di bawah ini.

[collapsed title=Spoiler: Select Parent Form] Aplikasi Inventory Sederhana Desain User Interface Visual Inheritance BiruniLabs [/collapsed]

  • Menambahkan elemen user interface ke dalam frmItemEdit. Tambahkan semua elemen field yang diperlukan ke dalam form, sehingga tampak seperti desain form di bawah ini.

[collapsed title=Spoiler: Desain Awal Form Master Barang] Aplikasi Inventory Sederhana Desain User Interface Visual Inheritance BiruniLabs [/collapsed]

  • Setting konfigurasi data-binding untuk setiap elemen User Interface. Pertama-tama pilih TextBox kode barang, kemudian cari property Text dalam group DataBinding, kemudian klik tombol dropdown dan pilih field code dari table items sebagai data-binding-nya seperti tampak pada gambar di bawah ini.

[collapsed title=Spoiler: Setting Property Data Binding] Aplikasi Inventory Sederhana Desain User Interface Visual Inheritance BiruniLabs [/collapsed]

  • Pada saat pertama kali kita melakukan setting data-binding, maka akan muncul beberapa komponen baru di bawah desain form, seperti tampak pada gambar di bawah ini. Selanjutnya lakukan setting data-binding untuk semua field lainnya.

[collapsed title=Spoiler: Tambahan Komponen Setelah Setting Data Binding Pertama Kali] Aplikasi Inventory Sederhana Desain User Interface Visual Inheritance BiruniLabs [/collapsed]

  • Menambahkan kode untuk membedakan inisialisasi data baru dengan edit data lama. Untuk membedakan proses inisialisasi databaru dengan edit data lama, maka kita manfaatkan constructor New dengan tambahan parameter id saat ketika kita ingin mengubah (edit) data lama.

[collapsed title=Spoiler: Kode Sumber Inisialisasi Form Edit]

    Public Sub New()
        ' This call is required by the designer.
        InitializeComponent()
        ' panggil inisialisasi database
        InitializeDatabase(-1)
    End Sub

    Public Sub New(ItemID As Integer)
        ' This call is required by the designer.
        InitializeComponent()
        ' panggil inisialisasi database
        InitializeDatabase(ItemID)
    End Sub

    Private Sub InitializeDatabase(ItemID As Integer)
        ' try retrieve data
        Try
            ' periksa nilai ItemID
            ' jika kurang dari 0 maka kita asumsikan mau bikin data baru
            ' jika lebih dari 0 maka kita asumsikan ambil bikin data lama
            If ItemID < 0 Then
                Me.BindingContext(Me.ItemsBindingSource).AddNew()
            Else
                Me.ItemsTableAdapter.FillByID(Me.DsInventory.items, ItemID)
            End If
        Catch ex As Exception
            MessageBox.Show("Error retrieving data from database\nDetails: " + ex.Message,
                Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        End Try
    End Sub

[/collapsed]

  • Menambahkan kode untuk menyimpan perubahan data ke database. Untuk menambahkan kode penyimpanan data ke database, bukalah designer form, kemudian klik ganda (double click) button [Save] dan tambahkan kode seperti di bawah ini.

[collapsed title=Spoiler: Kode Sumber Penyimpanan Data Ke Database]

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ' try saving data
        Try
            ' akhiri proses editing
            Me.BindingContext(Me.ItemsBindingSource).EndCurrentEdit()
            ' persist changes
            Me.ItemsTableAdapter.Update(Me.DsInventory)
            ' informasikan data berhasil disimpan
            MessageBox.Show("Data BERHASIL disimpan!",
                Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information)
            ' tutup form
            Me.Close()
        Catch ex As Exception
            MessageBox.Show("Error saving data to database\nDetails: " + ex.Message,
                Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
        End Try
    End Sub

[/collapsed]

Form List Barang

Sedangkan untuk melihat seluruh data barang yang tersimpan di database, kita akan membuatkan sebuah form list yang akan berisikan tombol-tombol (button) untuk proses tambah data, ubah data, dan delete data barang. Langkah-langkah yang perlu dilakukan antara lain,

  • Menyiapkan sebuah Inherited Form dari template frmList kemudian kita beri nama frmItemList. Cara membuat Inherited Form sama seperti saat kita membuat frmItemEdit di atas, silakan lakukan cara yang sama.
  • Berikutnya yang perlu kita lakukan adalah menambahkan elemen user interface ke dalam frmItemList. Elemen user interface yang harus di tambahkan di form list ini adalah DataGridView yang akan menampilkan seluruh data yang kita ambil dari database

[collapsed title=Spoiler: Desain Form List Master Barang]Aplikasi Inventory Sederhana Desain User Interface Visual Inheritance BiruniLabs[/collapsed]

  • Setting konfigurasi data-binding untuk setiap elemen User Interface. Proses setting data-binding ini bisa dilakukan lewat property Data Source, atau dapat juga dengan menggunakan shortcut context button kecil yang ada di atas design DataGridView, seperti tampak pada gambar di bawah ini.

[collapsed title=Spoiler: Konfigurasi Data Binding]Aplikasi Inventory Sederhana Desain User Interface Visual Inheritance BiruniLabs[/collapsed]

  • Jika kita membuka kode sumber untuk frmItemList ini, maka akan terlihat bahwa Visual Studio secara otomatis menambahkan sebaris kode untuk mengambil data dari database menggunakan data access layer yang kita buat pada artikel sebelumnya. Rupanya Visual Studio cukup cerdas dengan menmbahkan kode sumber yang diperlukan untuk mengantisipasi para developer yang terlupa menambahkannya.

[collapsed title=Spoiler: Auto Generate Code untuk Retrieve Data dari Visual Studio]Aplikasi Inventory Sederhana Desain User Interface Visual Inheritance BiruniLabs[/collapsed]

  • Menambahkan kode untuk mengambil data dari database. Proses pengambilan data (data retrieval) ini dilakukan pada saat Load Form, dimana kode sumbernya sudah ditambahkan secara otomatis oleh Visual Studio. Namun kita perlu tambahkan satu lagi ke button [Refresh] agar kita bisa mengambil ulang isi database. Caranya cukup dengan melakukan klik ganda (double click) pada button4 yang bertuliskan [Refresh]

[collapsed title=Spoiler: Kode Sumber untuk Proses Retrieve Data]

    Private Sub frmItemList_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'TODO: This line of code loads data into the 'DsInventory.items' table. You can move, or remove it, as needed.
        Me.ItemsTableAdapter.Fill(Me.DsInventory.items)
    End Sub

    Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
        Me.ItemsTableAdapter.ClearBeforeFill = True
        Me.ItemsTableAdapter.Fill(Me.DsInventory.items)
    End Sub

[/collapsed]

  • Menambahkan kode untuk menampilkan form tambah data baru. Untuk menambah data baru, kita perlu memanggil frmItemEdit tanpa menggunakan parameter apapun agar form edit barang tahu kita akan menambahkan data baru. Caranya cukup dengan melakukan klik ganda (double click) pada button1 yang bertuliskan [Add], kemudian tambahkan kode berikut ini

[collapsed title=Spoiler: Kode Sumber untuk Tambah Data Baru]

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ' start process
        Cursor = Cursors.AppStarting
        ' prepare variables
        Dim fx As frmItemEntry
        fx = New frmItemEntry
        ' tampilkan form
        fx.ShowDialog()
        ' refresh data, ambil data yang berubah
        Button4.PerformClick()
        ' finish process
        Cursor = Cursors.Default
    End Sub

[/collapsed]

  • Menambahkan kode untuk menampilkan form ubah data lama. Untuk mengubah data lama, yang kita perlu lakukan adalah memanggil frmItemEdit dengan memberikan parameter id agar form edit barang tahu kita akan menambahkan data baru. Caranya cukup dengan melakukan klik ganda (double click) pada button2 yang bertuliskan [Edit], kemudian tambahkan kode berikut ini

[collapsed title=Spoiler: Kode Sumber untuk Ubah Data Lama]

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
        ' start process
        Cursor = Cursors.AppStarting
        ' prepare variables
        Dim id As Integer
        Dim fx As frmItemEntry
        ' ambil id data yg akan diedit
        id = DataGridView1.SelectedRows(0).Cells("id").Value
        ' create form entry berdasarkan id yang dipilih
        fx = New frmItemEntry(id)
        ' refresh data, ambil data yang berubah
        Button4.PerformClick()
        ' tampilkan form
        fx.ShowDialog()
        ' finish process
        Cursor = Cursors.Default
    End Sub

[/collapsed]

  • Menambahkna kode untuk menghapus data barang. Untuk menghapus data, yang kita perlu lakukan adalah mengambil row data yang akan dihapus, kemudian melakukan konfirmasi ke pengguna apakah benar-benar akan menghapus data yang dimaksud. Caranya cukup dengan melakukan klik ganda (double click) pada button3 yang bertuliskan [Edit], kemudian tambahkan kode berikut ini,

[collapsed title=Spoiler: Kode Sumber untuk Hapus Data]

    Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
        ' start process
        Cursor = Cursors.AppStarting
        ' prepare variables
        Dim dr As DialogResult
        Dim id As Integer
        Dim code As String
        Dim name As String
        Dim message As String
        Dim pos As Integer
        ' ambil id dan code dari data yg akan diedit
        Dim dv As DataRowView
        dv = Me.BindingContext(Me.ItemsBindingSource).Current
        id = Convert.ToInt32(dv("id"))
        code = Convert.ToString(dv("code"))
        name = Convert.ToString(dv("name"))
        ' buat pesan konfirmasi
        message = String.Format("Are you sure to delete this [{0}] {1} data ? ", code, name)
        ' try deleting
        Try
            dr = MessageBox.Show(message,
                Application.ProductName, MessageBoxButtons.YesNo, MessageBoxIcon.Question)
            If dr = Windows.Forms.DialogResult.Yes Then
                pos = Me.BindingContext(Me.ItemsBindingSource).Position
                Me.BindingContext(Me.ItemsBindingSource).RemoveAt(pos)
                Me.ItemsTableAdapter.Update(Me.DsInventory)
                Me.DsInventory.AcceptChanges()
            End If
        Catch ex As Exception
            MessageBox.Show("Error deleting data from database\nDetails: " + ex.Message,
                Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Me.DsInventory.RejectChanges()
        End Try
        ' finish up
        Cursor = Cursors.Default
    End Sub

[/collapsed]

Simpulan

Jika kita perhatikan kode sumber yang kita tuliskan di aplikasi ini sangat sedikit sekali dikarenakan kita menggunakan metode data-binding. Kita juga tidak perlu lagi repot-repot membuat perintah SQL untuk proses CRUD, karena proses CRUD ini sudah ditangani di data access layer. Dengan makin sedikit-nya kode yang harus kita tuliskan tentunya akan semakin meningkatkan produktifitas kita semua sebagai programmer dan semakin banyak karya-karya fenomenal yang bisa kita buat.

Source Code

Untuk memudahkan teman-teman mempelajari hal ini, silakan Download Source Code Di SiniDibuat menggunakan Visual Studio 2013,  

Salam PojokProgrammer ^_^

 

/

Filter Data Menggunakan Tanggal dan Karakter di VB.net

Filter Pengambilan Data Menggunakan Tanggal dan Karakter di VB.net

Tips dan Trik | Saat membangun sebuah aplikasi database, pasti kita akan bertemu dengan kasus pengolahan data yang besar atau proses pengambilan (retrieval) data yang luar biasa banyak. Untuk memudahkan proses pengambilan data, dan pengolahannya, maka kita harus tahu bagaimana cara mengambil data dengan kriteria tertentu dari database. Proses Filter data ini menjadi penting karena sesungguhnya pengguna tidak memerlukan seluruh data yang ada di database, namun hanya sebagian kecil saja. Misalkan data transaksi keuangan yang tersimpan bisa jutaan row berisikan data beberapa tahun terakhir, biasanya pengguna hanya memerlukan data transaksi di bulan tertentu saja. Artikel ini akan mencoba menjelaskan cara melakukan filter data dari database berdasarkan beberapa kriteria sekaligus, yaitu berdasarkan string, angka, dan tanggal.

Misalkan kita memiliki 2 (dua buah table) yaitu Orders dan OrderTypes. Table Orders menyimpan data-data transaksi berikut dengan tanggal dan jenis transaksi. Table OrderTypes menyimpan definisi jenis-jenis transaksi yang ada, misalkan transaksi Purchase Order, Deliveri Order dan sebagainya. Penampakan isi table Orders adalah seperti pada gambar di bawah ini,

Filter Pengambilan Data Menggunakan Tanggal dan Karakter di VB.net

Sedangkan isi table OrderTypes seperti tampak pada gambar di bawah ini.

Filter Pengambilan Data Menggunakan Tanggal dan Karakter di VB.net

Kemudian kita coba buat sebuah desain form seperti tampak pada gambar di bawah ini. Kita akan menggunakan control TextBox untuk filter berdasarkan Nomor Transaksi, kemudian menggunakan DateTimePicker untuk filter berdasarkan tanggal transaksi, dan ComboBox untuk filter berdasarkan Jenis Transaksi. Dengan cara ini kita mendapatkan beberapa model filter sekaligus (y).

Filter Pengambilan Data Menggunakan Tanggal dan Karakter di VB.net

Berikutnya yang kita perlukan adalah code untuk proses-proses berikut ini

  • Inisialisasi kriteria filter tanggal transaksi
  • Inisialisasi kriteria filter jenis transaksi
  • proses pengambilan data dari database

Untuk proses pengambilan data dari database, aplikasi contoh kita menggunakan SQL Server 2012 LocalDB dengan connection string seperti di bawah ini

Private Const _cnString As String = "Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\dbSample.mdf;Integrated Security=True"

Untuk inisialisasi kriteria filter tanggal, maka kita cukup memberikan nilai tanggal ke control DateTimePicker berupa tanggal awal dan tanggal akhir tahun saja, dengan asumsi pengguna ingin melihat data pada tahun ini secara default. Maka code-nya akan tampak seperti ini.

    Private Sub InitializeDatePicker()
        ' set value date time picker ke awal dan akhir tahun
        DateTimePicker1.Value = "2014-01-01"
        DateTimePicker2.Value = "2014-12-31"
    End Sub

Untuk jenis transaksi, kita mengambil jenis-jenis transaksi yang tersedia di dalam tabel OrderTypes kemudian memuatnya ke ComboBox, sehingga code-nya akan tampak seperti ini

    Private Sub InitializeComboBox()
        ' siapkan koneksi database
        Dim cn As New SqlConnection(_cnString)
        ' siapkan data adapter untuk data retrieval
        Dim da As New SqlDataAdapter("select * from OrderTypes", cn)
        ' siapkan datatable untuk menampung data dari database
        Dim dt As New DataTable
        ' enclose di dalam try-catch block
        ' untuk menghindari crash jika terjadi kesalahan database
        Try
            ' ambil data dari database
            da.Fill(dt)
            ' bind data ke combobox
            ComboBox1.DataSource = dt
            ComboBox1.ValueMember = "ID"
            ComboBox1.DisplayMember = "Description"
            ' DONE!!!
        Catch ex As Exception
            ' tampilkan pesan error
            MessageBox.Show(ex.Message)
        End Try
    End Sub

Untuk proses penampilan data ke grid, maka yang kita lakukan adalah membuat perintah SQL berdasarkan kriteria yang diberikan pengguna kemudian mengambilnya dari database dan memuat data yang didapat ke dalam GridView. Maka code-nya akan tampak seperti di bawah ini.

    Private Sub RefreshGrid()
        ' siapkan koneksi database
        Dim cn As New SqlConnection(_cnString)
        ' siapkan data adapter untuk data retrieval
        Dim da As New SqlDataAdapter("SELECT A.*, B.Description AS TypeName " & _
                                     "FROM Orders A JOIN OrderTypes B ON A.TypeID=B.ID " & _
                                     "WHERE OrderNum LIKE @p1 AND TypeID = @t1 " & _
                                     "AND OrderDate BETWEEN @d1 AND @d2 ", cn)
        da.SelectCommand.Parameters.AddWithValue("@p1", "%" & TextBox1.Text & "%")
        da.SelectCommand.Parameters.AddWithValue("@t1", ComboBox1.SelectedValue)
        da.SelectCommand.Parameters.AddWithValue("@d1", DateTimePicker1.Value.ToString("yyyy-MM-dd"))
        da.SelectCommand.Parameters.AddWithValue("@d2", DateTimePicker2.Value.ToString("yyyy-MM-dd"))
        ' siapkan datatable untuk menampung data dari database
        Dim dt As New DataTable
        ' enclose di dalam try-catch block
        ' untuk menghindari crash jika terjadi kesalahan database
        Try
            ' ambil data dari database
            da.Fill(dt)
            ' bind data ke combobox
            DataGridView1.DataSource = dt
            ' DONE!!!
        Catch ex As Exception
            ' tampilkan pesan error
            MessageBox.Show(ex.Message)
        End Try
    End Sub

Secara keseluruhan, Code dalam Form kita menjadi seperti ini, termasuk di dalamnya procedure New dan Event Handler untuk menangani event click di tombol Filter.

Imports System.Data.SqlClient

Public Class Form1
    Private Const _cnString As String = "Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\dbSample.mdf;Integrated Security=True"

    Public Sub New()
        ' required by form designer
        InitializeComponent()
        ' inisialisasi datetimepicker
        InitializeDatePicker()
        ' inisialisasi combobox jenis transaksi
        InitializeComboBox()
        ' refresh grid data
        RefreshGrid()
    End Sub

    Private Sub InitializeDatePicker()
        ' set value date time picker ke awal dan akhir tahun
        DateTimePicker1.Value = "2014-01-01"
        DateTimePicker2.Value = "2014-12-31"
    End Sub

    Private Sub InitializeComboBox()
        ' siapkan koneksi database
        Dim cn As New SqlConnection(_cnString)
        ' siapkan data adapter untuk data retrieval
        Dim da As New SqlDataAdapter("select * from OrderTypes", cn)
        ' siapkan datatable untuk menampung data dari database
        Dim dt As New DataTable
        ' enclose di dalam try-catch block
        ' untuk menghindari crash jika terjadi kesalahan database
        Try
            ' ambil data dari database
            da.Fill(dt)
            ' bind data ke combobox
            ComboBox1.DataSource = dt
            ComboBox1.ValueMember = "ID"
            ComboBox1.DisplayMember = "Description"
            ' DONE!!!
        Catch ex As Exception
            ' tampilkan pesan error
            MessageBox.Show(ex.Message)
        End Try
    End Sub

    Private Sub RefreshGrid()
        ' siapkan koneksi database
        Dim cn As New SqlConnection(_cnString)
        ' siapkan data adapter untuk data retrieval
        Dim da As New SqlDataAdapter("SELECT A.*, B.Description AS TypeName " & _
                                     "FROM Orders A JOIN OrderTypes B ON A.TypeID=B.ID " & _
                                     "WHERE OrderNum LIKE @p1 AND TypeID = @t1 " & _
                                     "AND OrderDate BETWEEN @d1 AND @d2 ", cn)
        da.SelectCommand.Parameters.AddWithValue("@p1", "%" & TextBox1.Text & "%")
        da.SelectCommand.Parameters.AddWithValue("@t1", ComboBox1.SelectedValue)
        da.SelectCommand.Parameters.AddWithValue("@d1", DateTimePicker1.Value.ToString("yyyy-MM-dd"))
        da.SelectCommand.Parameters.AddWithValue("@d2", DateTimePicker2.Value.ToString("yyyy-MM-dd"))
        ' siapkan datatable untuk menampung data dari database
        Dim dt As New DataTable
        ' enclose di dalam try-catch block
        ' untuk menghindari crash jika terjadi kesalahan database
        Try
            ' ambil data dari database
            da.Fill(dt)
            ' bind data ke combobox
            DataGridView1.DataSource = dt
            ' DONE!!!
        Catch ex As Exception
            ' tampilkan pesan error
            MessageBox.Show(ex.Message)
        End Try
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        ' refresh grid data
        RefreshGrid()
    End Sub

End Class

Penampakan aplikasi berjalan adalah seperti ini

Filter Pengambilan Data Menggunakan Tanggal dan Karakter di VB.net

Selamat Belajar, Salam Pojok Programmer !

CRUD Sederhana – Insert Menggunakan MySqlCommand

Pojok Programmer - CRUD Sederhana - Insert Menggunakan MySqlCommand

CRUD Sederhana | Aplikasi database memerlukan pemahaman yang cukup karena banyak konsep yang harus dipahami sebelumnya, belum lagi komponen dan driver yang harus di-install sebelumnya. Namun .NET framework memudahkan kita untuk membuat coding database atau dikenal sebagai CRUD (Create Read Update Delete). Artikel ini akan membahas proses INSERT data ke database MySql menggunakan MySqlCommand. Pertama-tama kita siapkan table yang akan digunakan untuk menyimpan data. Silakan buka phpMyAdmin dan jalankan script SQL berikut ini untuk membuat table-nya

CREATE TABLE `pegawai` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `nip` varchar(50) CHARACTER SET utf8 DEFAULT NULL,
  `nama` varchar(50) CHARACTER SET utf8 DEFAULT NULL,
  `alamat` varchar(50) CHARACTER SET utf8 DEFAULT NULL,
  `tempat_lahir` varchar(50) CHARACTER SET utf8 DEFAULT NULL,
  `tanggal_lahir` date DEFAULT NULL,
  PRIMARY KEY (`id`)
);

Berikutnya kita buatkan Form sederhana yang berisikan TextBox untuk input data dan DataGridView untuk menampilkan data yang sudah tersimpan di database. Mungkin kira-kira tampilannya seperti ini, namun silakan jika teman-teman punya selera desain yang lain.

Pojok Programmer - CRUD Sederhana - Insert Menggunakan MySqlCommand

Pada awalprogram kita lakukan inisialisasi data dengan cara melakukan refresh terhadap isi grid, dengan menggunakan code seperti ini

Public Sub New()
    ' required by designer code
    InitializeComponent()
    ' required by this tutorial
    RefreshDataGrid()
End Sub

Private Sub RefreshDataGrid()
    ' siapkan koneksi database
    Dim cn As New MySqlConnection(cnString)
    Dim da As New MySqlDataAdapter("SELECT * FROM pegawai", cn)
    Dim dt As New DataTable
    ' coba ambil data
    Try
        ' masukkan data ke datatable
        da.Fill(dt)
        ' binding datatable ke grid
        DataGridView1.DataSource = dt
    Catch ex As Exception
        ' tampilkan error jika ada
        MessageBox.Show(ex.Message)
    End Try
End Sub

Sedangkan ini adalah code yang digunkan untuk meng-handle event click dari button Simpan.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    ' siapkan koneksi database
    Dim cn As New MySqlConnection(cnString)
    Dim cm As MySqlCommand
    Try
        ' siapkan perintah sql
        cm = cn.CreateCommand
        cm.CommandType = CommandType.Text
        cm.CommandText = "INSERT " & _
            "INTO pegawai(nip, nama, tempat_lahir, tanggal_lahir, alamat) " & _
            "VALUES (@nip, @nama, @tempat, @tanggal, @alamat)"
        ' gunakan parameter
        cm.Parameters.AddWithValue("@nip", TextBox1.Text)
        cm.Parameters.AddWithValue("@nama", TextBox2.Text)
        cm.Parameters.AddWithValue("@tempat", TextBox3.Text)
        cm.Parameters.AddWithValue("@alamat", TextBox4.Text)
        cm.Parameters.AddWithValue("@tanggal", DateTimePicker1.Value.ToString("yyyy-MM-dd"))
        ' buka koneksi database (wajib)
        cn.Open()
        ' jalankan perintah insert
        cm.ExecuteScalar()
        ' tutup koneksi (kalau tidak, dosa!)
        cn.Close()
        ' refresh data grid kembali
        RefreshDataGrid()
    Catch ex As Exception
        ' tampilkan error jika ada
        MessageBox.Show(ex.Message)
    End Try
End Sub

Dan Hasil akhirnya setelah dijalankan menjadi seperti ini

Pojok Programmer - CRUD Sederhana - Insert Menggunakan MySqlCommand

Silakan unduh source code di sini. Selamat Belajar

.

Aplikasi Inventory Sederhana – Data Access Layer

Aplikasi Inventory Sederhana - Data Access Layer

Aplikasi Inventory | Untuk memudahkan proses pembuatan Aplikasi Inventory sederhana atau Aplikasi Stok Barang ini, kita memerlukan sebuah Data Access Layer untuk proses pengambilan (retrieval) dan penyimpanan (persisting) data dari dan ke database yang kita gunakan, yaitu MySQL. Teknologi yang kita gunakan adalah ADO.net menggunakan DataSet dan DataAdapter. Dan untuk memudahkan kerja kita, maka kita akan menggunakan MySQL Installer for Windows untuk proses instalasi driver MySQL Connector/NET dan plugin MySQL for Visual Studio. Kekuatan ADO.net salah satunya ada di DataSet, dimana kita bisa membuat replika dari database fisik dan kemudian kita bisa menggunakannya secara object-oriented. 

 

Artikel ini adalah bagian dari artikel berseri tentang Tutorial Membuat Aplikasi Inventory Sederhana Menggunakan VB.net dan Database MySQL

 

Siapkan Koneksi Database

Langkah pertama adalah dengan membuka Server Explorer kemudian menambahkan koneksi baru ke database MySQL yang sudah kita siapkan di artikel sebelumnya. Perlu dicatat bahwa kita memerlukan plugin MySQL for Visual Studio agar dapat melakukan langkah-langkah tutorial di bawah ini, dan plugin ini hanya bisa digunakan di Visual Studio Professional ke atas, pada versi Express plugin ini tidak bisa digunakan.

Silakan tambahkan koneksi baru dan isikanlah form konfigurasi database, seperti contoh pada gambar di bawah ini

[collapsed title=Membuat Koneksi Baru di Server Explorer]

Pada Server Explorer, click icon Add New Connection sehingga muncul dialog box seperti di bawah ini

[collapsed title=Tentukan Data Source]

Aplikasi Inventory Sederhana - Data Access Layer Create Dataset

[/collapsed]

Kemudian isikan credential yang diperlukan untuk mengakses database mysql Anda, jika menggunakan paket xampp di localhost maka cukup isikan root sebagai user name dan kosongkan password.

[collapsed title=Isikan Credential Database]

Aplikasi Inventory Sederhana - Data Access Layer Create Dataset

[/collapsed]

Jika sukses, Anda dapat melihat seluruh tables, viwes, dan stored procedure yang ada di database.

[collapsed title=Penampakan Database di Server Explorer]

Aplikasi Inventory Sederhana - Data Access Layer Create Dataset

[/collapsed]

[/collapsed]

 

Membuat Typed-DataSet

Kekuatan ADO.net salah satunya ada di DataSet, dimana kita bisa membuat replika dari database fisik dan kemudian kita bisa menggunakannya secara object-oriented. Sedangkan DataSet sendiri ada 2 (dua) jenis, untyped-dataset dan typed-dataset. Disebut typed-dataset karena DataSet yang kita gunakan bukan dataset generic namun sudah dikonfigurasikan sesuai dengan schema database tertentu. Dengan menggunakan plugin MySQL for Visual Studio, kita bisa membuat Typed DataSet dengan cepat hanya dengan melakukan drag-and-drop dari Server Explorer.

[collapsed title=Membuat DataSet dengan Cara Drag-and-Drop dari Server Explorer]

Untuk membuat Typed DataSet pertama-tama buat sebuah Folder bernama Data di Solution Explorer, kemudian klik-kanan mouse pada folder Data tersebut dan pilihlah menu Add New Item

[collapsed title=Membuat DataSet kosong]

Aplikasi Inventory Sederhana - Data Access Layer Create Dataset

[/collapsed]

Berikan nama DataSet tersebut sebagai dsInventory, cukup logis karena kita sedang membuat sebuah Aplikasi Inventory. DataSet Designer kosong akan muncul seperti tampak pada gambar di screenshot ini.

[collapsed title=DataSet Designer kosong dengan nama dsInventory]

Aplikasi Inventory Sederhana - Data Access Layer Create Dataset

[/collapsed]

Drag-And-Drop. Langkah selanjutnya adalah membuka Server Explorer, kemudian lakukan Drag-And-Drop semua table yang ada di database ke atas DataSet Designer, sehingga akan terbentuk seperti gambar di bawah ini.

[collapsed title=Hasil setelah proses Drag-And-Drop dari Server Explorer]

Aplikasi Inventory Sederhana - Data Access Layer Create Dataset

[/collapsed]

Perlu diperhatikan bahwa Visual Studio secara otomatis membantu kita membuatkan semua fungsi SELECTINSERTUPDATE, dan DELETE dari semua table di atas pada saat proses Drag-And-Drop sehingga kita tidak perlu membuat semua query tersebut secara manual. Pastinya cara ini sangat meningkatkan produktifitas para programmer karena hal-hal seperti ini bisa kita otomasikan menggunakan Visual Studio.

[/collapsed]

 

Enhancing DataSet – Field Tambahan

Setelah kita berhasil membuat Typed-DataSet sesuai langkah-langkah di atas, langkah selanjutnya adalah melakukan enhancing, atau memberikan fungsi tambahan, terhadap DataSet yang sudah dibuatkan oleh Visual Studio. Tambahan fungsi ini meliputi field dan query untuk mempermudah kita melakukan pengambilan data dari database

[collapsed title=Enhancing DataSet – Field]

Membuat field tambahan ke table transactions, dengan cara meletakkan cursor pada posisi field yang mau kita tambahkan, kemudian klik-kanan mouse dan pilih menu Insert Column.

[collapsed title=Enhancing DataSet – Table Transactions]

Membuat field tambahan ke table transactions, dengan cara meletakkan cursor pada posisi field yang mau kita tambahkan, kemudian klik-kanan mouse dan pilih menu Insert Column.

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Buatlah semua field tambahan untuk table transactions sehingga menjadi seperti tampak di gambar di bawah ini.

[collapsed title=Enhancing DataSet – Table Transactions]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Buatlah semua field tambahan untuk table transaction_details sehingga menjadi seperti tampak di gambar di bawah ini.

[collapsed title=Enhancing DataSet – Table Transactions Details]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Perlu diperhatikan bahwa penambahan field diluar yang ada di table fisik nantinya akan sangat berguna ketika kita melakukan proses data binding  data ke control seperti DataGridView, sehingga kita tidak perlu membuat kolom tambahan lagi di DataGridView karena sudah tersedia semua di DataSet.

[/collapsed]

 

Enhancing DataSet – Query Tambahan

Berikutnya yang kita lakukan menambahkan query ke DataSet. Jika kita perhatikan di DataSet Designer, ada komponen khusus dibawah bable dengan nama xxxTableAdapter. Komponen TableAdapter ini adalah DataAdapter yang khusus dibuatkan untuk menangani proses CRUD dari tabel bersangkutan, jadi proses CRUD untuk table transactions ditangani oleh transactionsTableAdapter. Secara default, sudah tersedia method Fill dan GetData, namun kedua methos tersebut masih bersifat generic pada saat proses pengambilan data dari database akan mengambil keseluruhan data tanpa filter.

Untuk itu kita perlu menambahkan sejumlah query untuk memudahkan kita mengambil data dari database berdasarkan kriteria tersentu, pastinya kita akan memerlukan query untuk mendapatkan data transaksi dengan ID tertentu, atau nomor transaksi tertentu, atau bisa juga berdasarkan tanggal transaksi.

[collapsed title=Enhancing DataSet – Add Query]

Membuat query tambahan ke table items, dengan cara meletakkan cursor pada posisi header itemsTableAdapter yang mau kita tambahkan, kemudian klik-kanan mouse dan pilih menu Add Query. Seperti tampak di bawah ini.

[collapsed title=Enhancing DataSet – Add Items Query]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Setelah itu akan muncul dialog box wizard proses pembuatan TableAdapter Query seperti ini, pilih Use SQL Statement karena kita akan mengambil data menggunakan perintah SQL.

[collapsed title=Enhancing DataSet – Add Query Wizard]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Kemudian pilih SELECT which returns rows karena query kita menghasilkan rows dari table items, untuk option lain silakan teman-teman coba sendiri.

[collapsed title=Enhancing DataSet – Add Query Wizard]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Beginilah penampakan query terhadap table items berdasarkan field ID, perhatikan bahwa query di bawah ini memasukkan sebuah parameter @id yang harus kita berikan nanti ketika memanggil query ini.

[collapsed title=Enhancing DataSet – Add Query Wizard]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

 

Berikan nama untuk query ini, seperti tampak pada gambar di bawah ini.

[collapsed title=Enhancing DataSet – Add Query Wizard]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

 

Selesai! Visual Studio sudah membuatkan fungsi untuk membantu kita melakukan query ke table items di database berdasarkan field ID.

[collapsed title=Enhancing DataSet – Add Query Wizard]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Setelah menambahkan query pengambilan data items berdasarkan ID, maka penampakan DataSet akan menjadi seperti pada gambar di bawah ini.

[collapsed title=Enhancing DataSet – Add Items Query]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Berikutnya yang perlu kita lakukan adalah menambahkan semua query berdasarkan kriteria yang kita inginkan ke seluruh table yang ada dalam DataSet kita ini. Berikut ini penampakan query terhadap table items berdasarkan field Code.

[collapsed title=Enhancing DataSet – Add Query]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Penampakan DataSet setelah menambahkan query berdasarkan field ID dan dan field Code pada table items dan transaction_types seperti pada gambar di bawah ini.

[collapsed title=Enhancing DataSet – Add Query]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Berikut ini penampakan query terhadap table transactions berdasarkan field ID. Perhatikan bahwa pada query ini kita melakukan JOIN terhadap table transactions dan transaction_types. Lebih jauh tentang JOIN silakan pelajari artikel ini.

[collapsed title=Enhancing DataSet – Add Query]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Berikut ini penampakan query terhadap table transactions berdasarkan field Code. Untuk query ini kita juga lakukan JOIN dengan transaction_types.

[collapsed title=Enhancing DataSet – Add Query]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Berikut ini penampakan query terhadap table transactions berdasarkan field Date. Perhatikan bahwa kita menggunakan klausa BETWEEN di dalam klausa WHERE.

[collapsed title=Enhancing DataSet – Add Query]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset By Dae

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset By Date

[/collapsed]

Penampakan DataSet setelah menambahkan query berdasarkan field ID dan, field Code, dan field Date pada table transactions seperti pada gambar di bawah ini.

[collapsed title=Enhancing DataSet – Add Query]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Berikut ini penampakan query terhadap table transaction_details berdasarkan field Code.

[collapsed title=Enhancing DataSet – Add Query – Transactions Details by ID]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Berikut ini penampakan query terhadap table transaction_details berdasarkan field Trans_ID.

[collapsed title=Enhancing DataSet – Add Query – Transactions Details by Transaction ID]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Penampakan DataSet setelah menambahkan query berdasarkan field ID dan dan field Transaction ID pada table transaction_details seperti pada gambar di bawah ini.

[collapsed title=Enhancing DataSet – Add Query]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Dengan tersedianya fungsi-fungsi query tambahan pada DataSet yang kita buat di atas, maka pada saat proses pengambilan data, kita hanya perlu meamanggil fungsi-fungsi tersebut dan tidap perlu lagi membuat query secara manual. Sekali lagi, produktifitas programmer semakin meningkat dengan cara ini.

[/collapsed]

 

Denormalisasi

Apakah denormalisasi database itu? denormalisasi database adalah pelanggaran aturan normalisasi atau menjabarkan suatu desain database yang telah normal untuk meningkatkan performa pengaksesan data pada database. Database yang telah normal disini dimaksudkan database yang redundansi datanya minim sehingga data yang disimpan tidak mengalami kerancuan dalam proses pengaksesan. Namun denormalisasi yang kita lakukan di sini tidak secara fisik, namun hanya menggunakan fasilitas view yang ada di database.

[collapsed title=Denormalisasi]

Denormalisasi kita lakukan dengan melakukan JOIN terhadap seluruh tabel yang ada di database inventory kita. Nantinya view denormalisasi ini akan berguna saat membuat laporan. Dengan bantuan plugin MySQL for Visual Studio, kita bisa membuat sebuah View langsung dari IDE Visual Studio sehingga tidak perlu berpindah ke phpMyAdmin atau HeidiSQL untuk membuat view denormalisasi ini.

[collapsed title=Denormalisasi – Membuat View]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Setelah View berhasil kita buat, langkah berikutnya adalah menambahkan view tersebut ke dalam Data Access Layer yang kita buat, caranya sama cukup dengan melakukan drag-drop dari Server Explorer ke DataSet Designer, sehingga tampak seperti gambar di bawah ini.

[collapsed title=Denormalisasi – Drag View ke DataSet Designer]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Berikut ini penampakan query terhadap view transaction_denormalized berdasarkan field Trans_ID.

[collapsed title=Denormaslisasi – Add Query – untuk view]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Berikut ini penampakan query terhadap view transaction_denormalized berdasarkan field Trans_Code.

[collapsed title=Denormaslisasi – Add Query – untuk view]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Berikut ini penampakan query terhadap view transaction_denormalized berdasarkan field Item_ID.

[collapsed title=Denormaslisasi – Add Query – untuk view]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Berikut ini penampakan query terhadap view transaction_denormalized berdasarkan field Item_Code.

[collapsed title=Denormaslisasi – Add Query – untuk view]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

Penampakan Data Access Layer setelah kita melengkapi query untuk View transaction_denormalized.

[collapsed title=Denormalisasi – Hasil Query Tambahan untuk View]

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

[/collapsed]

[/collapsed]

 

Hasil Akhir

Setelah seluruh langkah di atas kita selesaikan, maka langkah pamungkas dalam pembuatan Data Access Layer ini adalah dengan melakukan compile atau build project ini. Setelah proses build selesai dilakukan maka kita akan mendapatkan sejumlah komponen baru tampil di toolbox seperti tampak pada gambar di bawah ini. Visual Studio otomatis akan mengenali komponen Data Access Layer buatan kita dan menambahkannya ke dalam toolbox, dan kita bisa melakukan drag-and-drop komponen-komponen tersebut ke dalam form-form buatan kita nantinya. Komponen tambahan ini nantinya akan kita pergunakan dalam pembuatan Aplikasi Inventory ini.

Aplikasi Inventory Sederhana - Data Access Layer Enhance Dataset

 

Penutup

Mudah-mudahan penjelasan tentang pembuatan Data Access Layer dapat dipahami dengan mudah, dan silakan kunjungi link di bawah ini untuk mengunduh source-code sementara.

[collapsed title=Spoiler: Download Source Code Di Sini] Dibuat menggunakan Visual Studio 2013, Silakan Download Source Code Di Sini [/collapsed]

 

Salam Pojok Programmer !

Performance Tuning Sederhana di MySQL Menggunakan Index

Performace Tuning Sederhana di MySQL Menggunakan Index

Database Tuning | Database Tuning adalah sejumlah aktifitas yang dilakukan untuk memperbaiki atau meningkatkan kinerja atau performance sebuah database. Aktifitas tuning ini meliputi banyak aspek dari software hingga hardware, antara lain I/O Tuning, DBMS Tuning, Query Tuning, dan Database Maintenance. Masing-masing memiliki tekniknya sendiri-sendiri, dan membutuhkan skill yang mumpuni. Namun kita tetap bisa mempelajari teknik-teknik dasarnya. Dalam artikel ini, kita akan mencoba melakukan Query Tuning dengan bantuan Database Index.

Umumnya programmer, pada saat mengembangkan sebuah aplikasi database, pasti akan membuat sebuah database dan memasukkan beberapa data contoh ke dalamnya. Pada saat pengembangan, tidak ada masalah dan kelihatannya semua baik-baik saja, namun seiring berjalannya waktu, aplikasi mulai terkesan lambat dan bisa jadi sampai hang. Hal ini terjadi karena biasanya programmer tidak pernah melakukan load testing menggunakan data besar, dalam artian, jumlah row yang buanyak.

Nah… untuk contoh kasus, kita akan menggunakan database MySQL dan membuat sebuah table sederhana saja berisikan 9 (sembilan) juta rows, caranya seperti terlihat di bawah ini… perlu waktu sekitar 2 menit untuk men-generate table contoh tersebut. Perlu diperhatikan, setelah perintah di bawah ini selesai, maka baru table saja yang dibuat, belum ada index.

mysql> -- --------------------------------------------------
mysql> -- coba bikin sebuah table raksasa dengan 9 juta rows
mysql> -- setelah selesai dibuat, table ini belum memiliki index
mysql> -- --------------------------------------------------
mysql> create table big_table as
    -> select @baris := @baris+1 as baris
    -> from ( select @baris := 0 ) x
    -> join ( select 1 kolom from information_schema.tables ) a
    -> join ( select 1 kolom from information_schema.tables ) b
    -> join ( select 1 kolom from information_schema.tables ) c ;
Query OK, 9938375 rows affected (2 min 25.70 sec)
Records: 9938375  Duplicates: 0  Warnings: 0

Salah satu teknik yang banyak digunakan dalam aplikasi database adalah pagination, dimana teknik ini mengharuskan kita mengetahui total rows yang ada dalam sebuah table untuk menentukan jumlah page yang ada. Coba kita lakukan query count(*) untuk mengetahui total rows dalam table tersebut, dan lihat waktu yang diperlukan untuk mendapatkan hasilnya ๐Ÿ™‚

mysql> -- --------------------------------------------------
mysql> -- coba hitung jumlah row yang ada di dalam big_table
mysql> -- terlihat mysql memerlukan waktu 19 detik 
mysql> -- untuk mendapatkan hasil yang kita inginkan
mysql> -- --------------------------------------------------
mysql> select count(*) from big_table ;
+----------+
| count(*) |
+----------+
|  9938375 |
+----------+
1 row in set (18.82 sec)

Rupanya perlu waktu 18 detik untuk mendapatkan hasilnya…. untuk user yang penyabar, mungkin hal ini tidak menjadi masalah besar. Sekarang kita coba lihat execution plan yang dipilih oleh mysql saat mengeksekusi perintah count(*) yang kita berikan, maka terlihat seperti di bawah ini, bahwa mysql melakukan full table scan, ditandai dengan type=ALL pada execution plan yang muncul. Full table scan artinya, mysql meload seluruh table ke memory dan menghitung row yang ada di dalamnya satu persatu…. wow….

mysql> -- --------------------------------------------------
mysql> -- jika kita lihat execution plan query tersebut
mysql> -- terlihat bahwa mysql melakukan full table scan 
mysql> -- ditandai dengan type=ALL ke seluruh 9 juta rows
mysql> -- --------------------------------------------------
mysql> explain
    -> select count(*) from big_table ;
+----+-------------+-----------+------+---------------+------+---------+------+---------+-------+
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows    | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+---------+-------+
|  1 | SIMPLE      | big_table | ALL  | NULL          | NULL | NULL    | NULL | 9938689 |       |
+----+-------------+-----------+------+---------------+------+---------+------+---------+-------+
1 row in set (0.00 sec)

Sekarang kita coba lagi dengan model query lain yang sangat umum, yaitu query searching dengan menggunakan WHERE clause. Kita coba mencari sebuah row tertentu yang kira-kira lokasinya ada di tengah-tengah table. Pada contoh di bawah ini bisa terlihat bahwa mysql tetap melakukan full table scan ke seluruh rows, padahal row yang kita inginkan sudah ditemukan di tengah-tengah table. Dan rupanya perlu waktu lebih lama, yaitu 19 detik, dibandingkan dengan proses count(*) yang hanya 18 detik.

mysql> -- --------------------------------------------------
mysql> -- coba kita test dengan query yang lain
mysql> -- yaitu mendapatkan sebuah row yang kira2 
mysql> -- berada di tengah2 table besar ini
mysql> -- lagi2 terlihat mysql memerlukan waktu 19 detik 
mysql> -- untuk mendapatkan hasil yang kita inginkan
mysql> -- --------------------------------------------------
mysql> select * from big_table
    -> where baris = 5346781 ;
+---------+
| baris   |
+---------+
| 5346781 |
+---------+
1 row in set (19.03 sec)

Execution plan mengkonfirmasikan bahwa mysql melakukan full table scan dari row pertama sampai row terakhir, padahal kita hanya menginginkan satu row saja… ๐Ÿ™‚

mysql> -- --------------------------------------------------
mysql> -- jika kita lihat execution plan query tersebut
mysql> -- terlihat juga bahwa mysql melakukan full table scan 
mysql> -- ditandai dengan type=ALL ke seluruh 9 juta rows
mysql> -- *padahal* kita hanya perlu 1 row saja yang ada di tengah
mysql> -- --------------------------------------------------
mysql> explain
    -> select * from big_table
    -> where baris = 5346781 ;
+----+-------------+-----------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table     | type | possible_keys | key  | key_len | ref  | rows    | Extra       |
+----+-------------+-----------+------+---------------+------+---------+------+---------+-------------+
|  1 | SIMPLE      | big_table | ALL  | NULL          | NULL | NULL    | NULL | 9938977 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.00 sec)

Mari kita buat index….. sabar….. 2 menit…. ๐Ÿ™‚

mysql> -- --------------------------------------------------
mysql> -- sekarang coba kita buat INDEX berdasarkan field baris
mysql> -- harap bersabar... karena cukup lama juga :)
mysql> -- --------------------------------------------------
mysql> create index big_table_pk on big_table(baris) ;
Query OK, 0 rows affected (2 min 4.21 sec)
Records: 0  Duplicates: 0  Warnings: 0

Index selesai dibuat, dan kita coba lakukan proses penghitungan jumlah rows menggunakan query yang sama seperti sebelumnya… dan hasilnya muncul dalam 10 detik, sebuah peningkatan yang luar biasa dari 18 detik menjadi 10 detik saja (y)

mysql> -- --------------------------------------------------
mysql> -- sekarang kita hitung  row yang ada di dalam big_table
mysql> -- rupanya terlihat ada peningkatan performance 
mysql> -- dari awalya perlu 19 detik, menjadi 10 detik saja
mysql> -- LUAR BIASA!
mysql> -- --------------------------------------------------
mysql> select count(*) from big_table ;
+----------+
| count(*) |
+----------+
|  9938375 |
+----------+
1 row in set (10.91 sec)

Jika kita lihat execution plan, maka mysql tidak lagi menggunakan full table scan, namun sekarang menggunakan index scan. walaupun masih melakukan scan ke seluruh rows sebanyak 9 juta, namun index scan jauh leih cepat dibandingkan full table scan.

mysql> -- --------------------------------------------------
mysql> -- jika kita lihat execution plan query tersebut
mysql> -- terlihat bahwa mysql tidak lagi melakukan full table scan 
mysql> -- namun melakukan index scan, jauh lebih cepat dari full table scan
mysql> -- --------------------------------------------------
mysql> explain
    -> select count(*) from big_table ;
+----+-------------+-----------+-------+---------------+--------------+---------+------+---------+-------------+
| id | select_type | table     | type  | possible_keys | key          | key_len | ref  | rows    | Extra       |
+----+-------------+-----------+-------+---------------+--------------+---------+------+---------+-------------+
|  1 | SIMPLE      | big_table | index | NULL          | big_table_pk | 9       | NULL | 9938977 | Using index |
+----+-------------+-----------+-------+---------------+--------------+---------+------+---------+-------------+
1 row in set (0.00 sec)

Sekarang kita coba query searching….. dan hasilnya muncul sangat cepat, hanya 0.05 detik …. LUAR BIASA!

mysql> -- --------------------------------------------------
mysql> -- sekarang kita test dengan query kedua
mysql> -- dan hasilnya sangat LUAR BIASA!
mysql> -- hanya perlu 0.05 detik dari sebelumnya 19 detik !!!
mysql> -- --------------------------------------------------
mysql> select * from big_table
    -> where baris = 5346781 ;
+---------+
| baris   |
+---------+
| 5346781 |
+---------+
1 row in set (0.05 sec)

Jika kita lihat execution plan, maka mysql tidak lagi melakukan scan ke seluruh rows, namun langsung menuju satu row yang kita inginkan. Peningkatan kinerja pencarian dari 19 detik menjadi 0.05 detik adalah peningkatan yang sangat LUAR BIASA!

mysql> -- --------------------------------------------------
mysql> -- jika kita lihat execution plan query tersebut
mysql> -- terlihat bahwa mysql melakukan index "big_table_pk" 
mysql> -- dan langsung menuju rows yang kita inginkan
mysql> -- --------------------------------------------------
mysql> explain
    -> select * from big_table
    -> where baris = 5346781 ;
+----+-------------+-----------+------+---------------+--------------+---------+-------+------+--------------------------+
| id | select_type | table     | type | possible_keys | key          | key_len | ref   | rows | Extra                    |
+----+-------------+-----------+------+---------------+--------------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | big_table | ref  | big_table_pk  | big_table_pk | 9       | const |    1 | Using where; Using index |
+----+-------------+-----------+------+---------------+--------------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)

Perlu diperhatikan bahwa INDEX yang kita buat berdasarkan FIELD yang terlibat dalam WHERE clause, sehingga Query Optimizer di MySQL otomatis akan mengenali index tersebut dan menggunakannya untuk proses pencarian. Jadi untuk teman-teman programmer yang belum membuat index di table yang mereka buat, mulailah buat dari sekarang. SEMOGA BERGUNA!

mysql> -- --------------------------------------------------
mysql> -- SEMOGA BERGUNA!
mysql> -- --------------------------------------------------
mysql>

(y)

Performace Tuning Sederhana di MySQL Menggunakan Index