sqlite 无法将数据插入到文件室数据库

de90aj5v  于 2023-01-21  发布在  SQLite
关注(0)|答案(1)|浏览(202)

我试图插入值到房间数据库,但它不工作,我检查了数据库,表没有创建。我已经创建了数据库,DAO和Java存储库,并在MainActivity Kotlin类的协程内调用插入dao。
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);
    }
}

MainActivity.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
  • 这是不是插刀的正确使用方法?
  • 我可以在此实现上做哪些改进?
ni65a41a

ni65a41a1#

您的代码(较少使用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(并等待它开始工作)?

已做出以下假设:

  • 根据,应用程序数据库是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'

这是不是插刀的正确使用方法?
是的
我可以在此实现上做哪些改进?
您可以消除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**aka autoGenerate=true引入了一个约束条件(规则),它强制生成的值大于任何曾经使用过的值,并且基于每个表。如果没有AUTOINCRMENT,生成的值将比当前最大值大1,因此允许重用已删除的行的值。

低效之处在于,SQLite创建了一个名为sqlite_sequence的表,用于存储分配的最高值,以了解已存在的行的值。每当生成值时,都需要读取并更新此附加表,因此documentation表示
AUTOINCREMENT关键字会增加额外的CPU、内存、磁盘空间和磁盘I/O开销,如果不是非常需要,应该避免使用。通常不需要使用该关键字。
以下是使用autoGenerate=true时的所有表格(再次使用App Inspection)

根据建议删除autoGenerate=true,则

    • 另一个改进**是取代了int或Integer,对此类列使用long或Long更为正确(INTEGER列类型和PRIMARY KEY),因此如果插入时未提供值,则生成一个值。该值可以超过int/Integer所能容纳的值(最大2147483647),因为SQLite最多可存储64位有符号整数(9223372036854775807)。
  • 如果使用AUTOINCREMENT,当达到这个巨大的值时,下一次插入将失败,并出现SQLITE_FULL错误。2如果没有这个错误,则将应用一个未使用的值(如果可用)。

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

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

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

即无明显差异,已添加数据(卸载应用程序,删除整个数据库)

相关问题