首页 > 解决方案 > 通过内容提供者创建表或直接访问 DBHelper?其他?

问题描述

我正在构建一个 Android 应用程序,该应用程序使用数据库帮助程序类和仅用于访问数据库的内容提供程序。我注意到,当我的应用程序启动时,它永远不会点击我的 DBHelper 类的 onCreate(),如果它们不存在的话,它具有用于表创建的所有 DDL。

我已经手动创建了一张表,并且已经确认我可以通过我的提供程序执行 CRUD 操作。我的目标是让内容提供者只访问 DBhelper 类,并让 UI 使用内容提供者进行 CRUD 操作。

我觉得我在这里缺少了部分椅子,并且可以使用一些帮助来理解这个过程应该如何工作,这样当我的应用程序启动时,系统将检查表是否存在并在它们不存在时创建。

我已经将我的 DBhelper 类实现为单例,这似乎有很多争论。

我知道在创建操作可以继续之前我确实需要获得一个可读或可写的数据库,至少我认为这是正确的。如果我应该通过在应用程序启动时从 MainActivity 的 onCreate 获取我的 db 类的实例来做到这一点,我遇到的问题是无法拼凑起来?或者,如果我应该在我的内容提供商中做一些事情来在应用程序启动时处理这个问题?仅供参考 - 如前所述,我确实在我的清单中注册了我的内容提供程序,在我的 MainActivity onCreate() 中,我已经成功地将我的内容提供程序用于手动构建的表上的 CRUD 操作。

非常感谢这里的任何方向。

这是我的 AppDB 类

class AppDatabase extends SQLiteOpenHelper{

    public static final String DATABASE_NAME = "wgutrack.db";
    public static final int DATABASE_VERSION = 1;

    public static final String CTINE          = "CREATE TABLE IF NOT EXISTS ";
    public static final String PKA            = " INTEGER PRIMARY KEY AUTOINCREMENT, ";
    private static final String TEXT_TYPE     = " TEXT";
    public static final String INTEGER_TYPE   = " INTEGER";
    private static final String COMMA_SEP     = ", ";
    private static final String NN            = " NOT NULL ";

    // Implement AppDatabase as a singleton
    private static AppDatabase instance = null;

    private AppDatabase(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    /**
     * Get an instance of the app's singleton db helper object
     * @param context The content provider's context
     * @return A SQLite DB helper object
     */
    static AppDatabase getInstance(Context context) {

        if (instance == null) {
            instance = new AppDatabase(context);
        }
        return instance;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

        // Create script for Terms table
        String sqlTerms;
        sqlTerms = CTINE + TermsContract.TABLE_NAME + " ("
                + TermsContract.Columns._ID + PKA
                + TermsContract.Columns.COL_TITLE + TEXT_TYPE + NN + COMMA_SEP
                + TermsContract.Columns.COL_START + INTEGER_TYPE + NN + COMMA_SEP
                + TermsContract.Columns.COL_END + INTEGER_TYPE + NN + ")";
        Log.d("SQLQRY", sqlTerms);
        db.execSQL(sqlTerms);

        // Create script for Courses table
        String sqlCourses;
        sqlCourses = CTINE + CoursesContract.TABLE_NAME + " ("
                + CoursesContract.Columns._ID + PKA
                + CoursesContract.Columns.COL_TITLE + TEXT_TYPE + NN + COMMA_SEP
                + CoursesContract.Columns.COL_STATUS + TEXT_TYPE + NN + COMMA_SEP
                + CoursesContract.Columns.COL_MENTOR_ID + INTEGER_TYPE + NN + COMMA_SEP
                + CoursesContract.Columns.COL_START + INTEGER_TYPE + COMMA_SEP
                + CoursesContract.Columns.COL_END + INTEGER_TYPE + COMMA_SEP
                + CoursesContract.Columns.COL_START_NOTIFY + INTEGER_TYPE + COMMA_SEP
                + CoursesContract.Columns.COL_END_NOTIFY + INTEGER_TYPE + ")";
        Log.d("SQLQRY", sqlCourses);
        db.execSQL(sqlCourses);

        // Create script for term / course map table
        String sqlMap;
        sqlMap = CTINE + TermsCourseMapContract.TABLE_NAME + " ("
                + TermsCourseMapContract.Columns._ID + PKA
                + TermsCourseMapContract.Columns.COL_TERM_ID + INTEGER_TYPE + COMMA_SEP
                + TermsCourseMapContract.Columns.COL_COURSE_ID + INTEGER_TYPE + ")";

        // Create script for Mentors table
        String sqlMentors;
        sqlMentors = CTINE + MentorsContract.TABLE_NAME + " ("
                + MentorsContract.Columns._ID + PKA
                + MentorsContract.Columns.COL_FIRST_NAME + TEXT_TYPE + NN + COMMA_SEP
                + MentorsContract.Columns.COL_LAST_NAME + TEXT_TYPE + NN + COMMA_SEP
                + MentorsContract.Columns.COL_PHONE + TEXT_TYPE + COMMA_SEP
                + MentorsContract.Columns.COL_EMAIL + TEXT_TYPE + ")";
        Log.d("SQLQRY", sqlMentors);
        db.execSQL(sqlMentors);

        // Create script for Assessments table
        String sqlAssessments;
        sqlAssessments = CTINE + AssessmentsContract.TABLE_NAME + " ("
                + AssessmentsContract.Columns._ID + PKA
                + AssessmentsContract.Columns.COL_TITLE + TEXT_TYPE + NN + COMMA_SEP
                + AssessmentsContract.Columns.COL_DESC + TEXT_TYPE + COMMA_SEP
                + AssessmentsContract.Columns.COL_TYPE + TEXT_TYPE + COMMA_SEP
                + AssessmentsContract.Columns.COL_COURSE_ID + INTEGER_TYPE + NN + ")";
        Log.d("SQLQRY", sqlAssessments);
        db.execSQL(sqlAssessments);

        // Create script for the Notes table
        String sqlNotes;
        sqlNotes = CTINE + NotesContract.TABLE_NAME + " ("
                + NotesContract.Columns._ID + PKA
                + NotesContract.Columns.COL_TITLE + TEXT_TYPE + NN + COMMA_SEP
                + NotesContract.Columns.COL_TEXT + TEXT_TYPE + NN + COMMA_SEP
                + NotesContract.Columns.COL_COURSE_ID + INTEGER_TYPE + NN + ")";
        Log.d("SQLQRY", sqlNotes);
        db.execSQL(sqlNotes);

        // Create script for the Goals table
        String sqlGoals;
        sqlGoals = CTINE + GoalsContract.TABLE_NAME + " ("
                + GoalsContract.Columns._ID + PKA
                + GoalsContract.Columns.COL_TITLE + TEXT_TYPE + NN + COMMA_SEP
                + GoalsContract.Columns.COL_DESC + TEXT_TYPE + NN + COMMA_SEP
                + GoalsContract.Columns.COL_DUE_DATE + INTEGER_TYPE + NN + COMMA_SEP
                + GoalsContract.Columns.COL_ASS_ID + INTEGER_TYPE + NN + ")";
        Log.d("SQLQRY", sqlGoals);
        db.execSQL(sqlGoals);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        switch (oldVersion) {
            case 1:
                // upgrade from version 1
                break;
            default:
                throw new IllegalStateException("onUpgrade() with unknown new version: " + newVersion);
        }
    }
}

标签: androidsqliteandroid-contentprovider

解决方案


我注意到,当我的应用程序启动时,它永远不会点击我的 DBHelper 类的 onCreate(),如果它们不存在的话,它具有用于表创建的所有 DDL。

类的onCreate方法在SQLIteOpenHelper创建数据库时运行一次。它不会在每次实例化子类的实例时运行。

在开发应用程序时,更改数据库结构的最简单方法是执行以下操作之一(假设数据可能会丢失):-

  • 从设备上的设置中删除/清除应用程序的数据并重新运行应用程序。
  • 卸载并重新安装应用程序,然后重新运行应用程序。
  • 在删除表的方法中使用合适的代码,onUpgrade然后调用更改的onCreate方法。

如果您需要保留数据,那么您可以在ALTER TABLEonUpgrade的限制范围内使用 ALTER 表的方法。

您可以通过查询sqlite_master表来检查表是否存在。这将返回一个有 5 列的游标,即:-

  • 类型
    • 一桌一桌
  • 命名实体的名称
  • tbl_name实体相关的表的名称。
  • 根页面
  • sql用于创建实体的 SQL

  • (实体与类型有关,例如表、索引、视图、触发器)

....当我的应用程序启动时,系统将检查表是否存在并在它们不存在时创建。

所以要检查 tablex 那么你可以使用

SELECT tbl_name FROM sqlite_master WHERE tbl_name = 'tablex' AND type = 'table';

因此,您可以采用以下方法:-

public boolean doesTableExist(String table_name) {
    boolean rv = false;
    String[] columns = new String[]{"sqlite_master"};
    String whereclause = "tbl_name=? AND type=?";
    String[] whereargs = new String[]{table_name,"table"};
    Cursor csr = yoursqlitedatabase.query("sqlite_master",columns,whereclause,wwhereargs,null,null,null);
    rv = csr.getCount() > 0;
    csr.close();
    return rv;
}
  • 如果您在 DBhelper 中包含上述内容,则Cursor csr = yoursqlitedatabase.query("sqlite_master",columns,whereclause,wwhereargs,null,null,null);可能是Cursor csr = this.getWritableDatabase().query("sqlite_master",columns,whereclause,wwhereargs,null,null,null);

    • 通常你会看到SQliteDatabase db = this.getWritabledatabase()然后db.query........

    • 然后,您可以将某些内容AppDatabase myDBHlper;作为类变量,然后myDBHelper = Appdatabase.getInstance(this)if (myDBHelper.doestableExist("your_table")) { ....... }要检查的类(活动)中进行。

当然,简单地使用CREATE TABLE IF NOT EXISTS ......就足够了。

您可以通过覆盖作为onOpenSQLiteOpenHelper(又名 DBHelper)子类的类的方法或该onConfigure方法来实现检查等。


推荐阅读