房间数据库 Table 在插入新数据后仍然是空的

Room Database Table is still empty after inserting new data

我刚刚完成 this tutorial 我的应用程序。

但我的问题是,即使在我插入数据之后,我的数据库仍然是空的。我通过在数据库浏览器中查看它来检查它并且其中没有记录。任何帮助将不胜感激。如果您需要更多信息,请告诉我。

Dao 对象class:

@Insert(onConflict = OnConflictStrategy.REPLACE)
void insertRecord(LocationDetails Details);

我的实体class:

@Entity(tableName = "location")
public class LocationDetails {

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @PrimaryKey(autoGenerate = true)
    private int id;
    private String jsonObjectString;
    private double latitude;
    private double longitude;
    private String locationType;

    public String getLocationType() {
        return locationType;
    }

    public void setLocationType(String locationType) {
        this.locationType = locationType;
    }

    public double getLatitude() {
        return latitude;
    }

    public void setLatitude(double latitude) {
        this.latitude = latitude;
    }

    public double getLongitude() {
        return longitude;
    }

    public void setLongitude(double longitude) {
        this.longitude = longitude;
    }

    public String getJsonObjectString() {
        return jsonObjectString;
    }

    public void setJsonObjectString(String jsonObjectString) {
        this.jsonObjectString = jsonObjectString;
    }

    public String toString() {
        return "Lat: " + latitude + ", Long: " + longitude;
    }
}

这是我的数据库控制器 class,我的 ViewModel 用来与数据库交互。

public class DatabaseController {

    private String TAG = getClass().getSimpleName();

    private static DatabaseController sInstance;
    private LiveData<List<LocationDetails>> mListOfLocations;
    private Database mDatabase;

    private DatabaseController(Context context) {
        mDatabase = Database.getDatabase(context);
    }

    public static DatabaseController getInstance() {
        return sInstance;
    }

    public static void initInstance(Context context) {
        sInstance = new DatabaseController(context);
    }

    public void addLocationRecord(LocationDetails locationDetails) {
        new insertAsyncTask(mDatabase).execute(locationDetails);
        Log.d(TAG, "Location Record Added Successfully");
    }

    private static class insertAsyncTask extends AsyncTask<LocationDetails, Void, Void> {

        private Database database;

        insertAsyncTask(Database database) {
            this.database = database;
        }

        @Override
        protected Void doInBackground(LocationDetails... databases) {
            database.mMyDao().insertRecord(databases[0]);
            return null;
        }
    }
}

我在每一步都添加了断点并进行了检查。整个代码运行没有任何异常或错误,但我的数据库中仍然没有添加任何记录。

这里回答的问题是一样的,但他的解决方案不同,所以不是重复的。

我第一次收到这些日志:

2018-10-26 18:18:41.329 27827-27827/genesis.com.getlocation D/DatabaseController: Location Record Added Successfully
2018-10-26 18:18:41.345 27827-27876/genesis.com.getlocation D/Surface: Surface::disconnect(this=0x990a1f00,api=1)
2018-10-26 18:18:41.346 27827-27944/genesis.com.getlocation W/SQLiteConnection: Could not change the database journal as DB was busy. Proceeding...
2018-10-26 18:18:41.347 27827-27876/genesis.com.getlocation D/GraphicBuffer: unregister, handle(0xaaf92040) (w:848 h:1264 s:848 f:0x1 u:0x000b00)
2018-10-26 18:18:41.347 27827-27876/genesis.com.getlocation D/GraphicBuffer: unregister, handle(0xaaf92400) (w:848 h:1264 s:848 f:0x1 u:0x000b00)
2018-10-26 18:18:41.347 27827-27876/genesis.com.getlocation D/GraphicBuffer: unregister, handle(0xaaf924c0) (w:848 h:1264 s:848 f:0x1 u:0x000b00)
2018-10-26 18:18:41.347 27827-27876/genesis.com.getlocation D/Surface: Surface::disconnect(this=0x990a1f00,api=1)
2018-10-26 18:18:41.362 27827-27944/genesis.com.getlocation W/SQLiteConnection: Could not change the database journal as DB was busy. Proceeding...
2018-10-26 18:18:41.369 27827-27944/genesis.com.getlocation D/SQLiteDatabase: beginTransaction()
2018-10-26 18:18:41.372 27827-27944/genesis.com.getlocation D/SQLiteDatabase: endTransaction()
2018-10-26 18:18:41.374 27827-27827/genesis.com.getlocation D/WindowClient: Remove from mViews: DecorView@74e9112[], this = android.view.WindowManagerGlobal@fbcfdce
2018-10-26 18:18:41.377 27827-27827/genesis.com.getlocation V/InputMethodManager: onWindowFocus: null softInputMode=32 first=false flags=#81810100
2018-10-26 18:18:41.380 27827-27944/genesis.com.getlocation D/SQLiteDatabase: beginTransaction()
2018-10-26 18:18:41.384 27827-27944/genesis.com.getlocation D/SQLiteDatabase: endTransaction()
2018-10-26 18:18:41.394 27827-27873/genesis.com.getlocation I/BufferQueueProducer: [SurfaceTexture-0-27827-0](this:0xa8461000,id:0,api:1,p:27827,c:27827) queueBuffer: fps=0.67 dur=4486.29 max=3892.05 min=17.56
2018-10-26 18:18:41.403 27827-27945/genesis.com.getlocation D/SQLiteDatabase: beginTransaction()
2018-10-26 18:18:41.405 27827-27945/genesis.com.getlocation D/SQLiteDatabase: endTransaction()

之后我总是收到这些日志:(不同之处在于数据库很忙):

 2018-10-26 18:18:08.788 27080-27080/genesis.com.getlocation D/ConfirmDialogFragment: onDialogButtonClicked
2018-10-26 18:18:08.788 27080-27080/genesis.com.getlocation D/ConfirmDialogFragmentViewModel: RadioButton value is Desimus
2018-10-26 18:18:08.788 27080-27080/genesis.com.getlocation D/ConfirmDialogFragmentViewModel: Name of place is  Khan Plaza
2018-10-26 18:18:08.789 27080-27080/genesis.com.getlocation D/DatabaseController: Location Record Added Successfully
2018-10-26 18:18:08.791 27080-27775/genesis.com.getlocation D/SQLiteDatabase: beginTransaction()
2018-10-26 18:18:08.805 27080-27775/genesis.com.getlocation D/SQLiteDatabase: endTransaction()
2018-10-26 18:18:08.824 27080-27166/genesis.com.getlocation D/Surface: Surface::disconnect(this=0x94b83e00,api=1)
2018-10-26 18:18:08.825 27080-27166/genesis.com.getlocation D/GraphicBuffer: unregister, handle(0xa6043c40) (w:848 h:1264 s:848 f:0x1 u:0x000b00)
2018-10-26 18:18:08.826 27080-27166/genesis.com.getlocation D/GraphicBuffer: unregister, handle(0xa60425c0) (w:848 h:1264 s:848 f:0x1 u:0x000b00)
2018-10-26 18:18:08.826 27080-27166/genesis.com.getlocation D/GraphicBuffer: unregister, handle(0xa6042680) (w:848 h:1264 s:848 f:0x1 u:0x000b00)
2018-10-26 18:18:08.826 27080-27166/genesis.com.getlocation D/Surface: Surface::disconnect(this=0x94b83e00,api=1)
2018-10-26 18:18:08.829 27080-27602/genesis.com.getlocation D/SQLiteDatabase: beginTransaction()
2018-10-26 18:18:08.831 27080-27602/genesis.com.getlocation D/SQLiteDatabase: endTransaction()
2018-10-26 18:18:08.859 27080-27080/genesis.com.getlocation D/WindowClient: Remove from mViews: DecorView@3ad944e[], this = android.view.WindowManagerGlobal@40be950
2018-10-26 18:18:08.867 27080-27080/genesis.com.getlocation V/InputMethodManager: onWindowFocus: null softInputMode=32 first=false flags=#81810100
2018-10-26 18:18:08.879 27080-27235/genesis.com.getlocation I/BufferQueueProducer: [SurfaceTexture-0-27080-1](this:0xa8460000,id:1,api:1,p:27080,c:27080) queueBuffer: fps=0.44 dur=4554.45 max=4532.60 min=21.85
2018-10-26 18:18:08.893 27080-27235/genesis.com.getlocation I/BufferQueueProducer: [SurfaceTexture-0-27080-1](this:0xa8460000,id:1,api:1,p:27080,c:27080) queueBuffer: slot 0 is dropped, handle=0xaaf91800

很可能您没有成功插入。

确保您在插入时获得主 ID 确保您在后台线程上执行插入操作。 确保您在后台线程上进行检索

此外,如果您在安装后对模型进行了更改,这将导致它无法访问数据库,因为模式不再与模型变量匹配。

因此请检查您的数据库创建代码行,并确保您可以处理架构更改,例如更改模型。破坏性回退很好,或者如果没有人使用它,请卸载并重新安装。

检查您的 LocationDetails class 是否实现了 Serializable。 在您的 class 扩展 RoomDatabase 中插入您想要以这种方式添加的 class

 @Database(entities = {
        LocationDetails.class,
     },version = 1, exportSchema = false)

并确保每次在数据库中 add/remove class 时更新版本号。 此外,我建议使用 room 的 1.1.1-rc1 版本,通过在 gradle

中添加此行,它比 1.1.1 更稳定
 implementation 'android.arch.persistence.room:runtime:1.1.1-rc1'

此外,我建议在线程中调用您的请求,在 Android 6+(可能有 7 个不太记得)设备的每个 AsyncTask 共享同一个线程并等待轮到执行DoInBackground 功能,有时最多不会花费 5-10 秒来启动您的任务。

我的另一个原因是我只复制了数据库文件(通常有 .db 扩展名的文件)而忽略了 -shm-wal 文件。

当我将这两个文件连同主数据库文件复制到我的 PC,并打开主 .db 文件时,表及其记录在我的数据库中成功显示观众。

注意: SQLite 数据库文件在设备上的 /data/data/<the-app-package-name>/databases 中可用。访问它们可能需要 root 权限。

如果您想将文件合并到主数据库文件,请参阅 及其答案。

例如,我为此创建了一个单独的 DAO(Kotlin 语言):

import androidx.room.Dao
import androidx.room.RawQuery
import androidx.sqlite.db.SimpleSQLiteQuery
import androidx.sqlite.db.SupportSQLiteQuery

@Dao
abstract class DatabaseDao {

    open suspend fun flushDatabase() {
        checkpoint(SimpleSQLiteQuery("pragma wal_checkpoint(full)"))
    }

    @RawQuery
    protected abstract suspend fun checkpoint(supportSQLiteQuery: SupportSQLiteQuery): Int
}