《第一行程式碼》閱讀筆記(二十三)——資料庫設計(補充)
廢話不多說,先看下結構
然後直接上程式碼
public class StudyProgressDBHelper extends SQLiteOpenHelper { //資料庫名 private static final String DB_NAME = "progress.db"; //資料庫版本號 private static final int DB_VERSION = 1;//9-16 09:38 2-->3 10-14 17:32 3-->4 11-8 14:14 4-->5 private Context mContext; //建構函式 public StudyProgressDBHelper(Context context) { super(context, DB_NAME, null, DB_VERSION); mContext = context; } //建立學習進度資料庫 private static final String CREATE_STUDY_PROGRESS = "create table if not exists " + StudyProgressDAO.TABLE_NAME + " (" + StudyProgressDAO.VOA_ID + " Integer NOT NULL primary key," + StudyProgressDAO.LESSON + " varchar(20) ," + StudyProgressDAO.LISTEN_TIME + " int," + StudyProgressDAO.USER_ID + " int," + StudyProgressDAO.TOTAL_LISTEN_TIME + " int," + StudyProgressDAO.RIGHT_QUE_NUM + " int," + StudyProgressDAO.TOTAL_QUE_NUM + " int," + StudyProgressDAO.IS_EVALUATION_SENT_NUM + " int," + StudyProgressDAO.TOTAL_SENT_NUM + " int" + ")"; @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_STUDY_PROGRESS); Timber.e("建立表成功"+CREATE_STUDY_PROGRESS); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { switch (oldVersion) { } } }
public interface StudyProgressDAO { String TABLE_NAME = "study_progress"; String VOA_ID = "voa_id"; String LESSON = "lesson"; String USER_ID = "user_id"; String LISTEN_TIME = "listen_time"; String TOTAL_LISTEN_TIME = "total_listen_time"; String RIGHT_QUE_NUM = "right_que_num"; String TOTAL_QUE_NUM = "total_que_num"; String IS_EVALUATION_SENT_NUM = "is_evaluation_sent_num"; String TOTAL_SENT_NUM = "total_sent_num"; public void setStudyProgress(int voaID, String databaseColumn, int value); public int getStudyProgress(String databaseColumn ,int voaID); public int getVoaId(int voaID); }
public class StudyProgressDAOImpl implements StudyProgressDAO { private final SQLiteDatabase db; StudyProgressDAOImpl(SQLiteDatabase db) { this.db = db; } @Override public void setStudyProgress(int voaID, String databaseColumn, int value) { String sql; if (getVoaId(voaID) == 0) { sql = "Insert Into " + TABLE_NAME + " ( " + VOA_ID + "," + databaseColumn + " )" + " VALUES (" + voaID + "," + value + ")"; } else { sql = " UPDATE " + TABLE_NAME + " SET " + databaseColumn + " = " + value + " WHERE " + VOA_ID + " = " + voaID; } db.execSQL(sql); } @Override public int getStudyProgress(String databaseColumn, int voaID) { String sql = " Select " + databaseColumn + " FROM " + TABLE_NAME + " WHERE " + VOA_ID + "= ?"; String[] args = {String.valueOf(voaID)}; Cursor cursor = db.rawQuery(sql, args); if (cursor != null && cursor.moveToFirst()) { return cursor.getInt(cursor.getColumnIndex(databaseColumn)); } else { return 0; } } @Override public int getVoaId(int voaID) { String sql = " SELECT voa_id FROM study_progress WHERE voa_id = ?" ; String[] args = {String.valueOf(voaID)}; Cursor cursor = db.rawQuery(sql, args); db.execSQL(sql); if (cursor != null && cursor.moveToFirst()) { return cursor.getInt(cursor.getColumnIndex(VOA_ID)); } else { return 0; } } }
public class StudyProgressDBManager implements StudyProgressDAO {
private static StudyProgressDBManager sInstance;
private static StudyProgressDAOImpl studyProgressDAOImpl;
public static void init(Context appContext) {
if (sInstance == null) {
sInstance = new StudyProgressDBManager(appContext);
}
}
public static StudyProgressDBManager getInstance() {
if (null == sInstance) throw new NullPointerException("not init");
return sInstance;
}
private StudyProgressDBManager(Context context) {
StudyProgressDBHelper dbHelper = new StudyProgressDBHelper(context);//onCreate
SQLiteDatabase db = dbHelper.getWritableDatabase();
studyProgressDAOImpl = new StudyProgressDAOImpl(db);
}
@Override
public void setStudyProgress(int voaID, String databaseColumn, int value) {
studyProgressDAOImpl.setStudyProgress(voaID,databaseColumn,value);
}
@Override
public int getStudyProgress(String databaseColumn, int voaID) {
return studyProgressDAOImpl.getStudyProgress(databaseColumn,voaID);
}
@Override
public int getVoaId(int voaID) {
return studyProgressDAOImpl.getVoaId(voaID);
}
}
大家看懂了沒有?這是公司裡面一個大神的資料庫設計方式,第一次看到也被這種清晰的結構所折服。接下來就讓筆者班門弄斧一下,給大家提供一些解釋吧。
StudyProgressDBHelper
public class StudyProgressDBHelper extends SQLiteOpenHelper {
//資料庫名
private static final String DB_NAME = "progress.db";
//資料庫版本號
private static final int DB_VERSION = 1;//9-16 09:38 2-->3 10-14 17:32 3-->4 11-8 14:14 4-->5
private Context mContext;
//建構函式
public StudyProgressDBHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
}
}
}
首先我們應該編寫的就是Helper類,這個類需要繼承SQLiteOpenHelper。其實大家在建立郭神的《第一行程式碼》中應該早就熟悉了這個類的使用。
在這個類中,我們需要確定包名和資料庫版本,均使用 public static final修飾,並提供一個環境的成員變數。
之後新增一個建構函式,在建構函式中直接呼叫父類的建構函式,傳入環境,資料庫名,null(工廠),資料庫版本,同時將環境賦值給成員變數。
然後重寫SQLiteOpenHelper的兩個方法,建立資料庫和更新資料庫,並把建立資料庫的SQL抽取出來,讓結構更加清晰。
StudyProgressDBManager
這個管理類就是整個資料庫設計的核心,在這裡採用非常常用的單例設計模式,這樣就可以有效的防止資料庫操作的衝突。
private static StudyProgressDBManager sInstance;
下面這三個函式就是Manager的核心
public static void init(Context appContext) {
if (sInstance == null) {
sInstance = new StudyProgressDBManager(appContext);
Timber.e("sInstance 建立");
}
}
public static StudyProgressDBManager getInstance() {
if (null == sInstance) throw new NullPointerException("not init");
return sInstance;
}
private StudyProgressDBManager(Context context) {
StudyProgressDBHelper dbHelper = new StudyProgressDBHelper(context);//onCreate
SQLiteDatabase db = dbHelper.getWritableDatabase();
Timber.e("資料庫建立成功");
}
init()函式接收的是一個Application的Context,然後判斷sInstance是不是null,如果不為空就呼叫StudyProgressDBManager的建構函式。常常這個函式會被放在自定義的Application中,這樣就可以在專案一被建立就例項化成功。
StudyProgressDBManager的建構函式中,首先例項化StudyProgressDBHelper,然後建立一個數據庫。
最後就是一個getInstance()的方法,如果sInstance成員變數不為空,就返回例項化的sInstance(在init()函式中被例項化)。
在後續的程式設計中如果需要例項Manager,實現以下程式碼即可。
private StudyProgressDBManager
studyProgressDBManager = StudyProgressDBManager.getInstance();
studyProgressDBManager.xxx
StudyProgressDAO
StudyProgressDAO是一個介面,相當於資料庫中的表,裡面的資訊有表名和欄位名。還有一些需要使用的方法,例如新增,查詢等。
編寫完成後,可以在helper類中,建立資料庫表。
//建立學習進度資料庫
private static final String CREATE_STUDY_PROGRESS = "create table if not exists " + StudyProgressDAO.TABLE_NAME + " (" +
StudyProgressDAO.VOA_ID + " Integer NOT NULL primary key," +
StudyProgressDAO.LESSON + " varchar(20) ," +
StudyProgressDAO.LISTEN_TIME + " int," +
StudyProgressDAO.USER_ID + " int," +
StudyProgressDAO.TOTAL_LISTEN_TIME + " int," +
StudyProgressDAO.RIGHT_QUE_NUM + " int," +
StudyProgressDAO.TOTAL_QUE_NUM + " int," +
StudyProgressDAO.IS_EVALUATION_SENT_NUM + " int," +
StudyProgressDAO.TOTAL_SENT_NUM + " int" + ")";
在create函式中新增。
db.execSQL(CREATE_STUDY_PROGRESS);
如果已經更新過一個版本,就需要增加DB_VERSION的值,並且使用update()更新資料庫。
StudyProgressDAOImpl
StudyProgressDAOImpl是StudyProgressDAO的實現類,實現StudyProgressDAO並繼承方法,其房費就是真正的資料庫操作。
其中還有一個建構函式,接收一個數據庫檔案,並傳遞給成員變數。
編寫完這個類之後,需要讓StudyProgressDBManager繼承StudyProgressDAO,然後重寫方法。並在StudyProgressDBManager建構函式中studyProgressDAOImpl = new StudyProgressDAOImpl(db);
例項化DAO的實現了。在重新DAO的方式的時候,直接使用Impl回撥,即可。