sql 数据库中具有多个表的活动崩溃 - Android Studio

Posted

技术标签:

【中文标题】sql 数据库中具有多个表的活动崩溃 - Android Studio【英文标题】:Activity with multiple tables in sql database crashes - Android Studio 【发布时间】:2021-11-01 04:27:12 【问题描述】:

我想为我的应用程序创建一个商店,但我被困住了,因为我无法在我的 sql 数据库中保存使商品的购物工作所需的数据。我使用了三个游标,每个表一个,但是当我尝试从数据库中检索该数据时,应用程序崩溃并出现以下错误:

2021-09-02 17:57:00.195 27466-27466/? E/com.example.a1:runtime_flags 中设置的未知位:0x8000 2021-09-02 17:57:00.218 27466-27466/? E/libc:访问被拒绝查找属性“runtime.mmitest.isrunning” 2021-09-02 17:57:00.395 27466-27501/com.example.a14 E/AwareLog:AtomicFileUtils:readFileLines 文件不存在:android.util.AtomicFile@feea179 2021-09-02 17:57:00.395 27466-27501/com.example.a14 E/AwareLog:AtomicFileUtils:readFileLines 文件不存在:android.util.AtomicFile@a63cebe

这是用于购买文章的方法。如果它工作正常,当用户选择文章时会调用方法Buy(),并使用分数、解锁文章和激活文章的变量,完成所有操作。这是Buy() 方法的代码:

    public void Buy(View view) 

    //Database conection
    AdminSQLiteOpenHelper admin = new AdminSQLiteOpenHelper(this, "administration", null, 3);
    SQLiteDatabase Database= admin.getWritableDatabase();

    //Database query
    Cursor row = Database.rawQuery("select * from saved_data ", null);
    Cursor row2 = Database.rawQuery("select * from unlocked_articles", null);
    Cursor row3 = Database.rawQuery("select * from activated_articles", null);

    ContentValues record = new ContentValues();

    final Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale);

    if (row.moveToFirst())  //If db is not empty...

        int score = row.getInt(2);

        if(row2.moveToFirst())

            int art0_unlock = row2.getInt(0); //One variable, one article
            int art1_unlock = row2.getInt(1);
            int art2_unlock = row2.getInt(2);
            int art3_unlock = row2.getInt(3);
            int art4_unlock = row2.getInt(4);

            if(row3.moveToFirst())

                int art0_activ = row3.getInt(0); 
                int art1_activ = row3.getInt(1);
                int art2_activ = row3.getInt(2);
                int art3_activ = row3.getInt(3);
                int art4_activ = row3.getInt(4);

                if (art0.isSelected())  ...  //Operations for the purchase are here, not the problem

                //For saving data

                record.put("score", score);

                record.put("art0_unlock", art0_unlock);
                record.put("art1_unlock", art1_unlock);
                record.put("art2_unlock", art2_unlock);
                record.put("art3_unlock", art3_unlock);
                record.put("art4_unlock", art4_unlock);

                record.put("art0_activ", art0_activ);
                record.put("art1_activ", art1_activ);
                record.put("art2_activ", art2_activ);
                record.put("art3_activ", art3_activ);
                record.put("art4_activ", art4_activ);

                Database.update("saved_data", record, null, null);
                Database.update("unlocked_articles", record, null, null);
                Database.update("activated_articles", record, null, null);

                tv_score.setText(score);

                row.close();
                row2.close();
                row3.close();


            else //If activated_articles is empty...

                record.put("art0_activ", 0);
                record.put("art1_activ", 0);
                record.put("art2_activ", 0);
                record.put("art3_activ", 0);
                record.put("art4_activ", 0);

                Database.insert("activated_articles", null, record);

                row3.close();

            

        else //If unlocked_articles is empty...

            record.put("art0_unlock", 0);
            record.put("art1_unlock", 0);
            record.put("art2_unlock", 0);
            record.put("art3_unlock", 0);
            record.put("art4_unlock", 0);

            Database.insert("unlocked_articles", null, record);

            row2.close();

        

        Database.close();

    


这是我的 AdminSQLiteOpenHelper 代码,值得知道 unlocked_articlesactivated_articles 稍后添加,这就是我调用 onUpgrade 方法的原因:

    package com.example.a14;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import androidx.annotation.Nullable;

public class AdminSQLiteOpenHelper extends SQLiteOpenHelper
    public AdminSQLiteOpenHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) 
        super(context, name, factory, version);
    

@Override
public void onCreate(SQLiteDatabase Database) 

    Database.execSQL("create table saved_data(victories int, lvls_unlocked int, score int)");

    Database.execSQL("create table unlocked_articles(art0_unlock int, art1_unlock int, art2_unlock int, art3_unlock int, art4_unlock int)");

    Database.execSQL("create table activated_articles(art0_activ int, art1_activ int, art2_activ int, art3_activ int, art4_activ int)");



@Override
public void onUpgrade(SQLiteDatabase Database, int i, int i1) 

    Database.execSQL("create table unlocked_articles(art0_unlock int, art1_unlock int, art2_unlock int, art3_unlock int, art4_unlock int)");

    Database.execSQL("create table activated_articles(art0_activ int, art1_activ int, art2_activ int, art3_activ int, art4_activ int)");

    onCreate(Database);


我不知道为什么这会导致应用崩溃,因为我没有发现错误。提前致谢。

【问题讨论】:

【参考方案1】:

您遇到的一个问题是,如果/当您走到那一步时,您正在尝试更新不存在的列。

也就是说,您构建了一个 ContentValues(即 record),其中包含来自所有 3 个表的列,然后您将其用于更新所有 3 个表。您将得到一个未找到的列 SQLiteException,例如:-

android.database.sqlite.SQLiteException: no such column: art2_activ (code 1 SQLITE_ERROR): , while compiling: UPDATE saved_data SET art2_activ=?,score=?,art3_unlock=?,art4_unlock=?,art2_unlock=?,art3_activ=?,art1_activ=?,art0_unlock=?,art1_unlock=?,art4_activ=?,art0_activ=?

即在saved_data表中找不到art2_activ列(该列属于activated_articles表)。

因此,您需要 3 个单独的 ContentValue,每个都适合各自的表格。我还建议在结束时关闭游标,而不管遵循的路径。

这是一个调用 Buy 方法的工作示例(在添加一些数据之前先两次,然后在添加一些数据之后):-

public class MainActivity extends AppCompatActivity 

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        AdminSQLiteOpenHelper db = new AdminSQLiteOpenHelper(this,"administration",null,3);
        Buy(); // test empty (if first run since install)
        
        /* NOTE insert methods added to the DB Helper to allow testing with some data */
        db.insertSaved(10,1,0);
        db.insertUnlocked(1,1,1,1,1);
        db.insertActivated(1,1,1,1,1);
        Buy(); // test with some data
    
    public void Buy(/*View view <<<<<< COMMENTED OUT*/ ) 
        //Database conection
        AdminSQLiteOpenHelper admin = new AdminSQLiteOpenHelper(this, "administration", null, 3);
        SQLiteDatabase Database= admin.getWritableDatabase();

        //Database query
        Cursor row = Database.rawQuery("select * from saved_data ", null);
        Cursor row2 = Database.rawQuery("select * from unlocked_articles", null);
        Cursor row3 = Database.rawQuery("select * from activated_articles", null);
        ContentValues cv_score = new ContentValues();
        ContentValues cv_unlock = new ContentValues();
        ContentValues cv_activ = new ContentValues();

        //final Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale); <<<<< COMMENTED OUT
        if (row.moveToFirst())  //If db is not empty...
            int score = row.getInt(2);
            if(row2.moveToFirst())
                int art0_unlock = row2.getInt(0); //One variable, one article
                int art1_unlock = row2.getInt(1);
                int art2_unlock = row2.getInt(2);
                int art3_unlock = row2.getInt(3);
                int art4_unlock = row2.getInt(4);

                if(row3.moveToFirst())
                    int art0_activ = row3.getInt(0);
                    int art1_activ = row3.getInt(1);
                    int art2_activ = row3.getInt(2);
                    int art3_activ = row3.getInt(3);
                    int art4_activ = row3.getInt(4);
                    //if (art0.isSelected())  ...  //Operations for the purchase are here, not the problem <<<<< COMMENTED OUT

                    //For saving data
                    cv_score.put("score",score);
                    cv_unlock.put("art0_unlock", art0_unlock);
                    cv_unlock.put("art1_unlock", art1_unlock);
                    cv_unlock.put("art2_unlock", art2_unlock);
                    cv_unlock.put("art3_unlock", art3_unlock);
                    cv_unlock.put("art4_unlock", art4_unlock);
                    cv_activ.put("art0_activ", art0_activ);
                    cv_activ.put("art1_activ", art1_activ);
                    cv_activ.put("art2_activ", art2_activ);
                    cv_activ.put("art3_activ", art3_activ);
                    cv_activ.put("art4_activ", art4_activ);
                    Database.update("saved_data", cv_score, null, null);
                    Database.update("unlocked_articles", cv_unlock, null, null);
                    Database.update("activated_articles", cv_activ, null, null);

                else //If activated_articles is empty...
                    cv_activ.put("art0_activ", 0);
                    cv_activ.put("art1_activ", 0);
                    cv_activ.put("art2_activ", 0);
                    cv_activ.put("art3_activ", 0);
                    cv_activ.put("art4_activ", 0);
                    Database.insert("activated_articles", null, cv_activ);
                

            else //If unlocked_articles is empty...
                cv_unlock.put("art0_unlock", 0);
                cv_unlock.put("art1_unlock", 0);
                cv_unlock.put("art2_unlock", 0);
                cv_unlock.put("art3_unlock", 0);
                cv_unlock.put("art4_unlock", 0);
                Database.insert("unlocked_articles", null, cv_unlock);
            
        
        row.close();
        row2.close();
        row3.close();
        Database.close();
    

注意部分代码已被注释掉 cv_scorecv_unlockcv_activ 已使用 3 个 ContentValues 而不是单个 ContentValues record。。李>

【讨论】:

我实施了您建议的更改,但 logcat 给了我同样的错误。

以上是关于sql 数据库中具有多个表的活动崩溃 - Android Studio的主要内容,如果未能解决你的问题,请参考以下文章

SQL:具有相似表的多个左连接

如何使用具有多个表的管道生成 SQL 输出

具有多个条件的 SQL 查询不起作用

具有产品 ID 和该 ID 的多个值的表的 Sql 查询

使用 SSIS 将具有多个表的单个 mdb 文件动态导入 SQL Server?

处理多个表的工作流