我在Room数据库中执行简单的@insert
操作时遇到了问题。这些是我的课程:
模型类
@Entity(tableName = "my_model")
data class MyModel(
@PrimaryKey @ColumnInfo(name = "id_model") var uid: Int,
@ColumnInfo(name = "name") var firstName: String,
@ColumnInfo(name = "last_name") var lastName: String
)
DAO界面
interface MyModelDAO {
@Insert
fun createMyModel(myModel: MyModel)
}
数据库
@Database(
entities = [(MyModel::class)],
version = 1,
exportSchema = false
)
abstract class MyDb : RoomDatabase() {
companion object {
private var INSTANCE: MyDb? = null
fun getInstance(context: Context): MyDb? {
if (INSTANCE == null) {
synchronized(MyDb::class) {
INSTANCE = Room.databaseBuilder(context.applicationContext,
MyDb::class.java, "mydb.db")
.allowMainThreadQueries()//for testing purposes only
.build()
}
}
return INSTANCE
}
fun destroyInstance() {
INSTANCE = null
}
}
abstract fun getMyModelDao(): MyModelDAO
}
这就是我要插入对象的方式。
val db = MinhaDb.getInstance(this)
db?.getMyModelDao()?.createMyModel(MyModel(111, "john", "doe"))
问题是,该操作未持久存储在db文件中。如果我进入databases
文件夹,则有一个mydb
文件,一个wal
和一个shm
文件,并且在mydb
中没有创建表。
但是,如果我在插入操作之后调用db?.close()
,则该操作将按其应有的方式发生(已创建并填充了表),并且wal
和shm
文件不存在。>
我在这里想念什么?我很确定我不必在数据库上调用close()
。我试过使用beginTransaction()
和endTransaction()
调用来包围插入调用,以查看它是否进行了更改,但是没有更改。
更新: 正如@musooff在评论中解释的那样,显然这就是sqlite dbs的工作方式。即使文件本身看起来是空的,我也要在插入调用以及返回的记录之后查询数据库。
答案 0 :(得分:3)
您的代码似乎运行正常。不要为SQLite创建的临时文件感到困惑。
db
文件来检查是否存在数据,则该数据可能还不存在。等待直到关闭连接。您已经注意到,在db目录中,您可以找到三个生成的文件:
your-database-name
your-database-name-shm
your-database-name-wal
但是,对您来说,真正重要的数据是your-database-name
。
wal
文件用来代替Rollback Journal。
从版本3.7.0(2010-07-21)开始,SQLite支持一种称为“预写日志”或“ WAL”的新事务控制机制。当数据库处于WAL模式时,与该数据库的所有连接都必须使用WAL。特定的数据库将使用回滚日志或WAL,但不会同时使用两者。 WAL始终与数据库文件位于同一目录中,并且与数据库文件具有相同的名称,但是附加了字符串“ -wal”。
您提到的关于wal
文件仍然存在时无法查看数据库文件中数据的信息,然后关闭连接,wal
文件消失并且数据被删除最终保留在数据库中,是使用wal
机制时的正确行为。
WAL消失
只要任何数据库连接都打开了数据库,WAL文件就存在。通常,与数据库的最后一个连接关闭时,WAL文件会自动删除。 (More here)
交易未立即写入数据库文件
传统的回滚日志的工作原理是将原始未更改的数据库内容的副本写入单独的回滚日志文件,然后将更改直接写入数据库文件。如果发生崩溃或ROLLBACK,则回滚日志中包含的原始内容会被回放到数据库文件中,以将数据库文件还原为原始状态。删除回退日志时,将发生COMMIT。
WAL的方法可以扭转这种情况。原始内容保留在 数据库文件和更改将附加到单独的WAL中 文件。当表示提交的特殊记录为 附加到WAL。 因此,无需写信即可进行COMMIT 原始数据库,使读者可以继续从 原始未更改的数据库,同时进行更改 承诺加入WAL 。可以将多个事务附加到 一个WAL文件的结尾。
当然,最终希望将WAL文件中附加的所有事务转移回原始数据库中。 将WAL文件事务移回数据库称为 “检查点”。
默认情况下,当WAL文件出现时,SQLite自动执行一个检查点 达到1000页的阈值大小。 ( SQLITE_DEFAULT_WAL_AUTOCHECKPOINT编译时选项可用于 指定不同的默认值。)使用WAL的应用程序不必这样做 为了使这些检查点发生而进行的任何操作。但是如果他们想要 到此,应用程序可以调整自动检查点阈值。要么 他们可以关闭自动检查点并在运行期间运行检查点 空闲时刻或在单独的线程或进程中。 (More here)
SHM 只是与WAL机制相关的临时共享内存文件,其唯一目的是:
共享内存文件不包含任何持久性内容。共享内存文件的唯一目的是提供一块共享内存,供所有在WAL模式下访问同一数据库的多个进程使用。 (More here)