【问题标题】:Android SQLite - New table VS. new DBAndroid SQLite - 新表 VS。新数据库
【发布时间】:2013-03-08 02:34:48
【问题描述】:

我的应用上有一个非常复杂的数据库。

当需要添加更多功能时,我开始考虑是否应该通过向现有数据库添加更多表来实现它,或者为添加的功能打开一个全新的数据库并在那里添加表。

是否有关于何时打开新数据库的基本规则?有没有关于该主题的基准?

【问题讨论】:

    标签: java android sql database sqlite


    【解决方案1】:

    当需要添加更多功能时,我开始怀疑 我是否应该通过向现有表中添加更多表来实现它 数据库,或为添加的功能打开一个全新的数据库 并在那里添加表格。

    是否有关于何时打开新数据库的基本规则?在那里 有关于该主题的可用基准吗?

    所以这是一个非常复杂的问题,取决于更多的因素,如应用程序的特性、所需的性能、表的特性、它们之间的关系等。

    很多人,很多意见,所以每个人都可以告诉你不同的东西。

    但我的意见是你应该只有一个数据库(什么时候会有更多的表,例如 10-20)。然后也试着想想Singleton的用法。

    总是最好将所有表放在一个数据库中,尤其是在这些表有共同点的情况下(有时需要连接两个或多个表,如果将表放到另一个数据库中,这将变得不可能) .此外,您不知道(现在确切地)将来是否会更新表、更改它们之间的关系等(例如,因为应用程序更新)。另一方面,应用程序的结构也更加干净和可读,就好像您在内部或外部存储中有五个 *.db 文件(我可以说这取决于每个文件的大小,因为将 100 MB .db 文件放置到内部存储)。

    关于实施的问题: 我建议您(如上所述)仅创建一个 DatabaseHelper 来包装所有必需的数据库逻辑。然后创建名为<?>Tools 的类(一个表一个类),例如将包装CRUD 操作和特定表的特定方法的UsersTools。我正在使用这种方法,从来没有遇到过问题。

    实现示例:

    这是 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";
    
    }
    

    TestTools 示例:

    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 开发者那里获得经验然后开始思考并决定合适的方法非常有用。

    【讨论】:

    • 非常感谢您的努力。这篇文章会成为一个很好的关于这个主题的教程。然而——正如我熟悉这里讨论的模式——我正在寻找一个更“硬核”的答案,也许不是围绕代码。你自己的指导方针是什么?
    • @Vaiden 所以我说的是,只创建一个数据库、一个 dbhelper 并创建与表一样多的类,其中每个类将为每个表包装 CRUD 操作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-02
    相关资源
    最近更新 更多