8

私のアプリにはかなり複雑なDBがあります。

機能を追加するときが来たとき、既存のデータベースにテーブルを追加して実装するのか、追加した機能用にまったく新しいデータベースを開いてそこにテーブルを追加するのか、疑問に思い始めました。

新しいDBをいつ開くかに関する基本的なルールはありますか?このテーマで利用できるベンチマークはありますか?

4

1 に答える 1

2

機能を追加するときが来たとき、既存のデータベースにテーブルを追加して実装するか、機能を追加するためにまったく新しいデータベースを開いてそこにテーブルを追加するかを考え始めました。

新しい DB をオープンするタイミングに関する基本ルールはありますか? この件に関して利用可能なベンチマークはありますか?

したがって、これは非常に複雑な問題であり、アプリケーションの特性、必要なパフォーマンス、テーブルの特性、テーブル間の関係など、より多くの要因に依存します。

多くの人、多くの意見があるので、誰もがあなたに何か違うことを言うことができます.

しかし、私の意見では、データベースは 1 つだけにする必要があります (また、10 ~ 20 相当のかなり多くのテーブルが必要になる場合もあります)。の使い方も考えてみてくださいSingleton

特にそれらのテーブルに共通点がある場合は、常にすべてのテーブルを1つのデータベースに配置することをお勧めします(2つ以上のテーブルを結合する必要があり、テーブルを別のデータベースに配置すると、これは不可能になります)。また、将来、テーブルを更新するかどうか、それらの間の関係を変更するかどうか(正確には今)もわかりません(たとえば、アプリケーションの更新のため)。一方、アプリケーションの構造も、たとえば*.db内部ストレージまたは外部ストレージに 5 つのファイルがあるかのように、よりクリーンで読みやすくなっています (100 MB の .db ファイルを内部ストレージに配置するのは面倒なので、これはそれぞれのサイズに依存すると言えます)。 .

実装に関する質問について: (上記のように) 必要なすべての db ロジックをラップする DatabaseHelper を 1 つだけ作成することをお勧めします。次に、特定のテーブルの操作と特定のメソッドを<?>Toolsラップする UsersTools などと呼ばれるクラス (1 つのテーブルに対して 1 つのクラス) を作成します。CRUD私はこのアプローチを使用していますが、問題はありませんでした。

実装例:

DatabaseHelper の例を次に示します。

package com.sajmon.examples.db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DataSource extends SQLiteOpenHelper {

    private static DataSource instance = null;

    public static final String DB_NAME = "<dbname>";
    public static final int DB_STARTING_VERSION = 1;

    public DataSource(Context cntx) {
        super(cntx, DB_NAME, null, DB_STARTING_VERSION);
    }

    /**
     * 
     * @param mContext as Context of Activity
     * @return <li>new instance of }DataSource object.</li>
     */
    public static DataSource getInstance(Context mContext) {
        if (instance == null) {
            instance = new DataSource(mContext);
        }
        return instance;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String query = "create table " + SQLConstants.TEST_TABLE_NAME + " ("
                + SQLConstants.KEY_ID + " integer not null, "
                + SQLConstants.KEY_TYPE + " text null, "
                + SQLConstants.KEY_DATE + " text null" + ")";
        db.execSQL(query);

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        String query = "drop table if exists " + SQLConstants.TEST_TABLE_NAME;
        db.execSQL(query);
        onCreate(db);
    }
}

SQL定数:

package com.sajmon.examples.db;

public class SQLConstants {

    public static final String TEST_TABLE_NAME = "Test";
    public static final String KEY_ID = "id";
    public static final String KEY_TYPE = "type";
    public static final String KEY_DATE = "date";

}

テストツールの例:

package com.sajmon.examples.db;

import java.util.Date;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;

public class TestTools {

private Context mContext;
private SQLiteDatabase db;

public TestTools(Context mContext) {
    this.mContext = mContext;
}

public boolean insert(Test t) throws SQLException {
    try {
        db = openWrite(DataSource.getInstance(mContext));
        ContentValues values = new ContentValues();
        if (db != null) {
            db.beginTransaction();
            values.put(SQLConstants.KEY_ID, t.getId());
            values.put(SQLConstants.KEY_TYPE, t.getType());
            values.put(SQLConstants.KEY_DATE, t.getDate());
            db.insertOrThrow(SQLConstants.TEST_TABLE_NAME, SQLConstants.KEY_TYPE, values);
            values.clear();
            db.setTransactionSuccessful();
            return true;
        }
        return false;
    }
    finally {
        if (db != null) {
            db.endTransaction();
        }
        close(db);
    }
}

public boolean update(Test t) {
    try {
        db = openWrite(DataSource.getInstance(mContext));
        ContentValues values = new ContentValues();
        int count = -1;
        if (db != null) {
            db.beginTransaction();
            values.put(SQLConstants.KEY_TYPE, t.getType());
            values.put(SQLConstants.KEY_DATE, t.getDate());
            count = db.update(SQLConstants.TEST_TABLE_NAME, values, SQLConstants.KEY_ID + "= ?", new String[] {t.getId()});
            db.setTransactionSuccessful();
        }
        return count > 0;
    }
    finally {
        if (db != null) {
            db.endTransaction();
            close(db);
        }
    }
}


public boolean delete(Test t) {
    int count = -1;
    try {
        db = openWrite(DataSource.getInstance(mContext));
        if (db != null) {
            db.beginTransaction();
            count = db.delete(SQLConstants.TEST_TABLE_NAME, SQLConstants.KEY_ID + "= ?", new String[] {t.getId()});
            db.setTransactionSuccessful();
        }
        return count > 0;
    }
    finally {
        if (db != null)
            db.endTransaction();
            close(db);
        }
    }
}

public List<Test> getAll() {
    Cursor c = null;
    List<Test> tests = new ArrayList<Test>();
    Test test = null;
    try {
        db = openRead(DataSource.getInstance(mContext));
        if (db != null) {
            String[] columns = {SQLConstants.KEY_ID, SQLConstants.KEY_TYPE, SQLConstants.KEY_DATE};
            c = db.query(SQLConstants.TEST_TABLE_NAME, columns, null, null, null, null, null);
            if (c.moveToFirst()) {
                do {
                    test = new Test();
                    test.setId(c.getInt(c.getColumnIndex(SQLConstants.KEY_ID)));
                    test.setType(c.getString(c.getColumnIndex(SQLConstants.KEY_TYPE)));
                    test.setDate(c.getString(c.getColumnIndex(SQLConstants.KEY_DATE)));
                    tests.add(test);        
                } while(c.moveToNext());
            }
        }
        return tests;
    }
    finally {
        if (c != null) {
            c.close();
        }
        if (db != null) {
            close(db);
        }
    }
}

private final synchronized SQLiteDatabase openWrite(SQLiteOpenHelper handler) {
    return handler.getWritableDatabase();
}

private final synchronized SQLiteDatabase openRead(SQLiteOpenHelper handler) {
    return handler.getReadableDatabase();
}

private final synchronized void close(SQLiteDatabase db) {
    if (db != null && db.isOpen()) {
        db.close();
    }
}
}

個々の要件に基づいていつでも変更/改善できる基本的な実装例です。そして、「より抽象的なレベル」で実装したい場合は、DAOFactoryデザインパターンが最適です。

注:他の Android 開発者から経験を積み、それについて考え始め、適切なアプローチを決定するのに非常に役立ちます。

于 2013-03-19T12:26:36.303 に答える