繁体   English   中英

无法将数据插入 Room 数据库

[英]Unable to insert data to Room database

我正在尝试将值插入房间数据库,但它不起作用,我检查了数据库,但没有创建表。 我在 java 中创建了数据库、DAO 和存储库,并在 MainActivity Kotlin class 中的协程中调用插入 dao。

@Insert
public void addExpense(List<Expenses> exp);

资料库

public class Repository {
    private ExpensesDao expensesDao;
    private SubscriptionsDao subscriptionsDao;
    private static AppDatabase db;

    public Repository(Context context) {
        initDb(context);
        expensesDao = db.expensesDao();
        subscriptionsDao = db.subscriptionsDao();
    }

    private static void initDb(Context context) {

        if (db == null) {
            db = Room.databaseBuilder(
                            context,
                            AppDatabase.class, "local_db"
                    )
                    .addMigrations(AppDatabase.DbMigration)
                    .build();
        }

    }

    public void addExpense(List<Expenses> exp) {
        expensesDao.addExpense(exp);
    }
}

主活动.kt

class MainActivity : AppCompatActivity() {

    private var firstRun = true

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val db = Repository(applicationContext)
        var spacesList: List<String> = listOf("No Spaces Found")

        var expList: List<Expenses> = listOf(
            Expenses("dummy", LocalDate.now().toString(), 12.22, "dummy1"),
            Expenses("dummy", LocalDate.now().toString(), 12.22, "dummy2"),
            Expenses("dummy", LocalDate.now().toString(), 13.22, "dummy3"),
            Expenses("dummy", LocalDate.now().toString(), 14.22, "dummy4"),
            Expenses("dummy", LocalDate.now().toString(), 15.22, "dummy5"),
            Expenses("dummy", LocalDate.now().toString(), 16.22, "dummy6")
        )

        CoroutineScope(Dispatchers.IO).launch {
            // the insert call
            val x = db.addExpense(expList)
            println("-->> "+x.toString())
        }

        val tempSpacesList = db.getAllSpaces().value
        if (tempSpacesList?.isEmpty() == true) {
            spacesList = tempSpacesList
        }

    }
}

编辑

@Entity
public class Expenses {

    public Expenses(String space, String date, double amount, String description) {
        this.uid = uid;
        this.space = space;
        this.date = date;
        this.amount = amount;
        this.description = description;
    }

    @PrimaryKey(autoGenerate = true)
    int uid;

    @ColumnInfo(name = "space")
    String space;

    @ColumnInfo(name = "date")
    String date;

    @ColumnInfo(name = "amount")
    double amount;

    @ColumnInfo(name = "description")
    String description;
}

Logcat(这里不多..)

15:11:55.340  E  Could not remove dir '/data/data/org.android.app/code_cache/.ll/': No such file or directory
  • 这是使用 insert dao 的正确方法吗?
  • 我可以在此实施上改进什么?

您的代码(较少使用 Subscirptions 和 getAllApaces)即 MainActivity 是:-

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val db = Repository(applicationContext)
        var spacesList: List<String> = listOf("No Spaces Found")

        var expList: List<Expenses> = listOf(
            Expenses("dummy", LocalDate.now().toString(), 12.22, "dummy1"),
            Expenses("dummy", LocalDate.now().toString(), 12.22, "dummy2"),
            Expenses("dummy", LocalDate.now().toString(), 13.22, "dummy3"),
            Expenses("dummy", LocalDate.now().toString(), 14.22, "dummy4"),
            Expenses("dummy", LocalDate.now().toString(), 15.22, "dummy5"),
            Expenses("dummy", LocalDate.now().toString(), 16.22, "dummy6")
        )

        CoroutineScope(Dispatchers.IO).launch {
            // the insert call
            val x = db.addExpense(expList)
            println("-->> "+x.toString())
        }

        /*
        val tempSpacesList = db.getAllSpaces().value
        if (tempSpacesList?.isEmpty() == true) {
            spacesList = tempSpacesList
        }
         */
    }
}

与 AppInspection 一起显示:-

在此处输入图像描述

也许您的问题在于您如何查看表是否存在 您是否使用过 App Inspection(并等待它开展业务)?

做出了以下假设:

  • AppDatabase 为 Java

:-

@Database(entities = {Expenses.class}, exportSchema = false, version = 1)
abstract class AppDatabase extends RoomDatabase {
    abstract ExpensesDao expensesDao();
}
  • 房间的依赖项是(根据模块 build.gradle)

:-

kapt 'androidx.room:room-compiler:2.5.0'
implementation 'androidx.room:room-ktx:2.5.0'
implementation 'androidx.room:room-runtime:2.5.0'
annotationProcessor 'androidx.room:room-compiler:2.5.0'
  • 插件部分包括

:-

id 'kotlin-kapt'

这是使用 insert dao 的正确方法吗?

是的

我可以在此实施上改进什么?

您可以消除autoGenerate=true的低效使用,它实际上不会导致自动生成,而是添加AUTOINCREMENT关键字,但接受 0 不是 0,而是将 0 的值解释为无值,从而生成值。

那就是你可以使用:-

@Entity
public class Expenses {

   public Expenses(String space, String date, double amount, String description) {
      this.space = space;
      this.date = date;
      this.amount = amount;
      this.description = description;
   }

   @PrimaryKey
   Integer uid= null; /* <<<<<<<< now Inetger (object not primitive) so can be null
   ....

AUTOINCREMENT又名autoGenerate=true引入了一个约束(规则),强制生成的值大于任何曾经使用过的值和每个表的基础。 如果没有 AUTOINCRMENT,生成的值将比当前最大值大 1,从而允许重用已删除的行的值。

效率低下是为了知道已存在的行的值 SQLite 创建了一个名为 sqlite_sequence 的表,该表存储最高分配的值。 每当生成值时都需要读取和更新此附加表,因此文档

AUTOINCREMENT 关键字强加额外的 CPU、memory、磁盘空间和磁盘 I/O 开销,如果不是严格需要,应避免使用。 通常不需要。

这是使用autoGenerate=true时的所有表格(再次使用 App Inspection)

在此处输入图像描述

然后建议删除autoGenerate=true

在此处输入图像描述

另一个改进是,对于此类列(INTEGER 列类型和 PRIMARY KEY),使用 long 或 Long 代替 int 或 Integer 更正确,因此在插入时如果不提供值,则生成一个值。 该值可以超过 int/Integer 可以容纳的值(最大 2147483647),因为 SQLite 存储最多 64 位签名的 integer(9223372036854775807)。

  • 使用 AUTOINCREMENT 当达到这个巨大的值时,下一个插入将失败并出现 SQLITE_FULL 错误。 如果没有,则将应用未使用的值(如果可用)。

此外,实际生成的值可能非常有用,因为它唯一标识行(尤其是在使用表之间的关系时)。 您可以在插入一行或多行时获取此值,但它将作为 long 而不是 Int 返回。 您还可以在再次插入多行而不是整数时检索值数组。 所以你可以: -

@Insert
public long[] addExpense(List<Expenses> exp); /* or Long[] */
  • 如果使用@Insert(onConflict = OnConflictStrategy.IGNORE)那么如果一行由于可忽略的冲突(例如重复)而被忽略,那么该插入的值将为 -1。

根据建议的更改,App Inspection 显示:-

在此处输入图像描述

即没有明显的区别,数据已添加(应用程序已卸载删除整个数据库)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM