Hướng dẫn tạo một ứng dụng cơ bản. Sử dụng mô hình lập trình 3 lớp để tương tác với Sqlite trong lập trình Android. Tài liệu hướng dẫn cách tạo một cơ sở dữ liệu Sqlite, cách thêm cơ sở dữ liệu vào trong Project trong Eclipse. Ví dụ cơ bản với thêm, sửa, xóa.
Trang 1MỤC LỤC
I Giới thiệu về mô hình 3 lớp 2
1.1 Understanding Three-Layer Model: 2
1.2 Các thành phần trong 3 – Layer 2
1.3 Cách vận hành của mô hình 3
II Xây dựng ứng dụng 4
2.1 Xây dựng Cơ sở dữ liệu: 4
2.2 Tạo một mới một cơ sở dữ liệu 6
2.3 Xây dựng ứng dụng, sử dụng theo mô hình 3 lớp 8
2.4 Khai báo quyền cho ứng dụng 26
2.5 Giao diện ứng dụng 27
Trang 2MÔ HÌNH LẬP TRÌNH 3 LỚP - SQLITE TRÊN ANDROID
Mục đích của tài liệu:
- Tài liệu này sẽ hướng dẫn các bạn cách lập trình thao tác cơ sở dữ liệu Sqlite trong lập trình Android theo Mô hình 3 lớp, giống như lập trình 3 lớp thao tác với cơ sở dữ liệu Sql Server trong CSharp
I Giới thiệu về mô hình 3 lớp
1.1 Understanding Three-Layer Model:
Để dễ quản lý các thành phần của hệ thống, cũng như không bị ảnh hưởng bởi các thay đổi, người ta hay nhóm các thành phần có cùng chức năng lại với nhau và phân chia trách nhiệm cho từng nhóm để công việc không bị chồng chéo và ảnh hưởng lẫn nhau Một trong những mô hình lập trình như vậy đó là Mô hình 3 lớp (Three Layers)
Lưu ý: Lớp này không nên sử dụng trực tiếp các dịch vụ của lớp Data Access mà nên sử dụng thông qua các service của lớp Business Logic vì khi bạn sử dụng trực tiếp như vậy, bạn có thể bỏ qua các ràng buộc, các logic nghiệp vụ mà ứng dụng cần phải có
2 Business Logic Layer (Lớp 2)
Trang 3- Đây là layer xử lý chính các dữ liệu trước khi được đưa lên hiển thị trên màn hình hoặc xử
lý các dữ liệu trước khi chuyển xuống Data Access Layer để lưu dữ liệu xuống cơ sở dữ liệu Đây là nơi đê kiểm tra ràng buộc, các yêu cầu nghiệp vụ, tính toán, xử lý các yêu cầu và lựa chọn kết quả trả về cho Presentation Layers
3 Data Access Layer (Lớp 1)
- Lớp này thực hiện các nghiệp vụ liên quan đến lưu trữ và truy xuất dữ liệu của ứng dụng như đọc, lưu, cập nhật cơ sở dữ liệu
1.3 Cách vận hành của mô hình
Đối với 3-Layer, yêu cầu được xử lý tuần tự qua các layer như hình
- Đầu tiên User giao tiếp với Presentation Layers (GUI) (mục số 3) để gửi đi thông tin và yêu cầu Tại layer này, các thông tin sẽ được kiểm tra, nếu OK chúng sẽ được chuyển xuống Business Logic Layer (BLL) (mục số 2)
- Tại BLL, các thông tin sẽ được nhào nặn, tính toán theo đúng yêu cầu đã gửi, nếu không cần đến Database thì BLL sẽ gửi trả kết quả về GUI, ngược lại nó sẽ đẩy dữ liệu (thông tin đã xử lý) xuống Data Access Layer (DAL) (mục số 1)
- DAL sẽ thao tác với Database và trả kết quả về cho BLL, BLL kiểm tra và gửi nó lên GUI để hiển thị cho người dùng
- Một khi gặp lỗi (các trường hợp không đúng dữ liệu) thì đang ở layer nào thì quăng lên trên layer cao hơn nó 1 bậc cho tới GUI thì sẽ quăng ra cho người dùng biết
- Các dữ liệu được trung chuyển giữa các Layer thông qua một đối tượng gọi là Data Transfer Object (DTO), đơn giản đây chỉ là các Class đại diện cho các đối tượng được lưu trữ trong Database (mục số 4)
Trang 4II Xây dựng ứng dụng
2.1 Xây dựng Cơ sở dữ liệu:
Các bạn tạo cơ sở dữ liệu bằng một ứng dụng hỗ trợ Lưu lại với định dạng sqlite Các bạn
có thể kết hợp các ứng dụng với nhau vì mỗi ứng dụng lại có một ưu nhược điểm khác nhau Ở trong bài này, mình sử dụng 2 ứng dụng
1 SQLite Administrator
2 SQLite manager (Một tiện ích có sẵn trong Firefox)
Sau khi cài đặt:
Trang 5Kéo thả tiện ích vào thanh công cụ như trong hình:
Khi chạy tiện ích sẽ được như trong hình:
Trang 62.2 Tạo một cơ sở dữ liệu mới, đặt tên là MyDatabase để thực hành ví dụ
- Bạn tạo một bảng dữ liệu mới đặt tên là SinhVien Chọn phải chuột vào Tables => Create Table Đặt tên bảng là SinhVien Chọn Add Field để thêm các trường
Trang 7- Sau khi thêm 3 trường, ta chọn Create:
- Ta được như sau:
Trang 8- Việc thêm, sửa, xóa, lấy dữ liệu ta sẽ thực hiện trong ứng dụng
2.3 Xây dựng ứng dụng, sử dụng theo mô hình 3 lớp
- Tạo ứng dụng android application, cấu trúc như sau:
(Bạn copy file MyDatabase.sqlite vừa tạo vào trong thư mục Access của Project)
Trong đó:
1 Packet com.kmt.Example: thuộc lớp thứ 3 là lớp Giao diện Dùng để tương tác dữ liệu với
người dùng (hiển thị dữ liệu, nhận dữ liệu để thêm, sửa và xóa)
2 Packet dataaccesslayer: Thuộc lớp 1 trong mô hình 3 lớp Gồm 2 Class
Trang 9- AssetDatabaseOpenHelper: Có nhiệm vụ Copy file Database từ thư mục Access vào
thư mục Database của ứng dụng Vì ứng dụng chỉ tương tác với cơ sở dữ liệu trong thư
mục databases có cấu trúc đường dẫn:
///data/data/{package của bạn}/databases
VD: String path = "/data/data/com.kmt.databaseaccess/databases";
(Chú ý: Bạn chỉ có thể truy cập vào File Explorer khi chạy máy ảo)
Nếu bạn chỉ copy file CSDL vào thư mục Access của Projetc thì ứng dụng vẫn không gọi được nó Khi bạn dùng lớp này thì khi chạy ứng dụng, nó sẽ kiểm tra đã tồn tại CSDL
trong thư mục database hay chưa, nếu chưa thì nó sẽ copy file CSDL từ thư mục Access
của Project vào cho chúng ta một cách tự động
Trang 10Hoặc bạn có thể tự copy thủ công bằng cách sau: Chọn thư mục database trong Packet
của ứng dụng trong thư mục File Exploder => Chọn Push a file onto the device
Chọn đến file CSDL mà bạn muốn import vào, chọn Open
CODE:
package databaseaccess;
/**
* Created by locnt_000 on 9/29/2015
Trang 11public class AssetDatabaseOpenHelper {
// tên file datebase trong thư mục assets
private static final String DB_NAME = "MyDatabase.sqlite";
private Context context;
public AssetDatabaseOpenHelper(Context context) {
this.context = context;
}
public void StoreDatabase() {
///data/data/{package của bạn}/databases
String path = "/data/data/com.kmt.databaseaccess/databases";
File pathDb = new File(path);
try {
// kiểm tra nếu có thư mục databases thì sẽ tạo
if (!pathDb.exists()){
pathDb.mkdir();
Trang 12} // kiểm tra file đó chưa tồn tại thì copy vào // điều kiện này tránh trường hợp mỗi lần mở ứng dụng sẽ copy vào
if (!new File(path + "/" + DB_NAME).exists()) {
copy(path);
} } catch (IOException e) {
private void copy(String path) throws IOException {
// mở file trong thư mục assets
InputStream is = context.getAssets().open(DB_NAME);
FileOutputStream fos = new FileOutputStream(path + "/" + DB_NAME);
byte buffer[] = new byte[1024];
int length;
//đọc và ghi vào thư mục databases
while ((length = is.read(buffer)) > 0) {
fos.write(buffer, 0, length);
}
is.close();
Trang 13- DBAdapter: Lớp đầu tiên của mô hình Thực hiện nhiệm vụ kết nối tới cơ sở dữ liệu Đóng,
mở kết nối Thực hiện các truy vấn, tác động tới cơ sở dữ liệu
public class DBAdapter {
private static final String TAG = "DBAdapter";
private static final String DB_NAME = "MyDatabase.sqlite";
private static final String DATABASE_NAME = "MyDatabase";
Trang 14private static String DATABASE_TABLE = "";
private static String DATABASE_CREATE = "";
private static final int DATABASE_VERSION = 1;
private Context context;
private DatabaseHelper DBHelper;
private SQLiteDatabase db;
private ContentValues contenValues;
private AssetDatabaseOpenHelper asset;
public DBAdapter(Context ctx, String DATABASE_TABLE, String
DATABASE_CREATE)
{
try {
asset = new AssetDatabaseOpenHelper(ctx);
asset.StoreDatabase(); // Kiểm tra, nếu chưa copy database từ thư mục asset vào thư mục database của ứng dụng thì copy
this.context = ctx;
DBHelper = new DatabaseHelper(ctx);
this.DATABASE_TABLE = DATABASE_TABLE;
this.DATABASE_CREATE = DATABASE_CREATE;
Trang 15* Sử dụng để cập nhật, nâng cấp cơ sở dữ liệu
Log.w(TAG, "Upgrading database from version " + oldVersion + " to " + newVersion
+ ", which will destroy all old data");
db.execSQL("DROP TABLE IF EXISTS '"+ DATABASE_TABLE +"'"); // xóa bảng
dữ liệu cũ
Trang 16onCreate(db); // Tạo lại bảng dữ liệu.
Trang 17db.execSQL("DROP TABLE IF EXISTS '"+ DATABASE_NAME +"'"); // xóa bảng dữ liệu cũ.
* Insert dữ liệu vào trong một bảng bất kỳ
* @param DATABASE_TABLE : Tên bảng cần Insert dữ liệu
* @param fields : Mảnh chứa tên các trường cần thê dữ liệu
* @param values : Mảng chứa giá trị cần thêm vào các trường theo thứ tự tương ứng */
public void InsertIntoTable(String[] fields, String[] values)
for (String field : fields) {
contenValues.put(field, values[i]);
i++;
}
Trang 18result = db.insert(DATABASE_TABLE, null, contenValues);
Toast.makeText(context, "Error InsertIntoTable: "+ e, Toast.LENGTH_SHORT).show();
* Update dữ liệu vào 1 bảng
* @param DATABASE_TABLE : Tên bảng
* @param fields : Danh sách các trường cần cập nhật dữ liệu
* @param values : Danh sách các giá trị mới
* @param whereClause : Mệnh đề điều kiện Form: tentruong1 = ? and tentruong2 = ? or tentruong3 = ?
* @param whereArgs : Danh sách các tham số truyền vào mệnh đề điều kiện
*/
public void UpdateTable(String[] fields, String[] values, String whereClause, String[] whereArgs)
{
Trang 19for (String field : fields) {
contenValues.put(field, values[i]);
i++;
} result = db.update(DATABASE_TABLE, contenValues, whereClause, whereArgs);
if (result == 0) { // lỗi Không có bản ghi nào được tác động
Toast.makeText(context, "Can't Update.",
Toast.makeText(context, "Error UpdateTable: "+ e, Toast.LENGTH_SHORT).show();
Trang 20* @param DATABASE_TABLE : Tên bảng cần xóa dữ liệu
* @param whereClause : Điều kiện
* @param whereArgs : Giá trị tham số của điều kiện
* Nếu xóa hết cả bảng: 2 tham số cuối để: NULL
Toast.makeText(context, "Error DeleteTable: "+ e, Toast.LENGTH_SHORT).show();
* Truy vấn lấy về dữ liệu trong bảng
* @param DATABASE_TABLE : Bảng cần lấy dữ liệu
Trang 21* @param columns : Các trường cần lấy
* @param selection : Mệnh đề điều kiện
* @param selectionArgs : Danh sách giá trị các tham số
* Truy vấn lấy giá trị dựa vào câu truy vấn bất kỳ
* @param sql : Câu truy vấn
* @param selectionArgs : Danh sách các giá trị của tham số trong mệnh đề điều kiện (nếu có)
Trang 243 Packet object Sử dụng để lưu trữ các giá trị của các đối tượng thuộc lớp SinhViên - Data
Transfer Object (DTO)
package object;
public class SinhVien {
// Các biến sử dụng cho lớp đối tượng Sinh Viên
private String Name = "", ClassName = "";
private intID = 0;
// Thiết lập và lấy các giá trị của một đối tượng thuộc lớp Sinh Viên
public int getID() {
return ID; }
public void setID(int iD) {
ID = iD;
}
public String getName() {
return Name; }
public void setName(String name) {
Name = name;
}
public String getClassName() {
return ClassName;
Trang 25public class DtSinhVien {
private DBAdapter dbAdapter ;
//private DatabaseHelper DBHelper;
private final Context context ;
private SQLiteDatabase db ;
private static final int DATABASE_VERSION = 1;
static final String DATABASE_CREATE =
"CREATE TABLE [SinhVien] ( [ID] INTEGER DEFAULT '0' NOT NULL PRIMARY KEY AUTOINCREMENT, [Name] TEXT NULL, [Class] TEXT NULL)";
// Các biến sử dụng cho một bảng cụ thể Dùng để truy xuất, tác động dữ liệu.
private static final String DATABASE_TABLE = "SinhVien";
private static final String KEY_ROWID = "id";
private static final String KEY_NAME = "Name";
private static final String KEY_CLASS = "Class";
private static final String[] COLUMNS = {KEY_ROWID,KEY_NAME,KEY_CLASS };
public DtSinhVien(Context context)
Toast.makeText(context, "Lỗi khi tạo đối tượng DBAdapter
"+ e, Toast.LENGTH_SHORT).show();
}
Trang 26}
// -insert a contact into the
public void insertSinhVien(String[] fields, String[] values)
{
dbAdapter InsertIntoTable(fields, values);
}
// -deletes a particular
public void deleteSinhVien(String whereClause, String[] whereArgs)
{
dbAdapter DeleteTable(whereClause, whereArgs);
}
// -retrieves all the
public Cursor getAllSinhVien()
{
try {
return dbAdapter SqlQuery(COLUMNS,null, null);
} catch (Exception e) {
Toast.makeText(context , "Lỗi tại truy vấn GetAllContact "+
e, Toast.LENGTH_SHORT).show();
return null;
} }
// -retrieves a particular
public Cursor getSinhVien(long rowId) throws SQLException
2.4 Khai báo quyền cho ứng dụng
- Để ứng dụng có quyền tác động (Gọi, thêm, sửa, xóa) vào cơ sở dữ liệu Bạn cần khai báo
quyền cho ứng dụng trong file AndroidManifest.xml:
- < uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- < uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" />
Trang 272.5 Giao diện ứng dụng
- Nhập thử dữ liệu, rồi nhấn Insert:
Trang 28- Nhấn Get để load lại dữ liệu:
Tướng tự với sửa, xóa
******************* Chúc các bạn thành công *****************************