Android 从房间数据库返回项目计数

Android 从房间数据库返回项目计数,android,android-room,android-threading,Android,Android Room,Android Threading,我试图阻止从房间数据库中删除父对象,如果它有通过外键关联的子对象 我在做学位追踪。如果某学期有课程,则不能删除该学期。如果该学期没有课程,则可以删除该学期。我正在尝试获取相关术语id的课程数,并使用简单的if语句删除没有课程的术语,如果有课程,则使用弹出警报,并指示用户在删除术语之前删除课程 来自activity.java switch(item.getItemId()){ ... case R.id.delete_term: int coursecount = queryCourses(te

我试图阻止从房间数据库中删除父对象,如果它有通过外键关联的子对象

我在做学位追踪。如果某学期有课程,则不能删除该学期。如果该学期没有课程,则可以删除该学期。我正在尝试获取相关术语id的课程数,并使用简单的if语句删除没有课程的术语,如果有课程,则使用弹出警报,并指示用户在删除术语之前删除课程

来自activity.java

switch(item.getItemId()){
...
case R.id.delete_term:

int coursecount = queryCourses(termIdSelected);

    if(coursecount > 0){
                    AlertDialog.Builder a_builder = new 
                    AlertDialog.Builder(TermEditorActivity.this);
                    a_builder.setMessage("Courses are assigned for this 
                    term!\n\nYou must remove all courses" +
                            "prior to deleting this term.")
                            .setCancelable(false)
                            .setPositiveButton("Okay", new 
                             DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, 
                                int which) {

                                    finish();
                                }
                            });
                    AlertDialog deleteAllAlert = a_builder.create();
                    deleteAllAlert.setTitle("CANNOT DELETE TERM!!!");
                    deleteAllAlert.show();
                    return true;
                }else{
                    mViewModel.deleteTerm();
                    startActivity(new Intent(TermEditorActivity.this, 
                    MainActivity.class));
                }
...
public int queryCourses(int term) {
        int course = mViewModel.queryCourses(term);
        return course;
    }
从ViewModel中:

public int queryCourses(final int term) {
        int course = mRepository.queryCourses(term);
        return course;
    }
从Approvitory(这是我认为事情会分崩离析的地方):

来自TermDAO:

@Query("SELECT COUNT(*) FROM course WHERE term_id = :termIdSelected")
    int queryCourses(int termIdSelected);
这会导致运行时错误,当按下“删除”按钮时会崩溃。这个概念很简单-使用术语的id查询课程数据库,以获取具有术语id外键的课程数。如果没有,请删除术语并返回术语列表。如果有课程(计数>0),请提醒用户并在不删除的情况下完成

不带线程的异常:

java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
当使用线程时,它会删除包含或不包含课程的术语,并且当有课程附加到术语时,不会显示任何警报。在调试模式下运行时,当有一个课程时,coursecount返回0,因此查询未正常运行

我需要做些什么来获取线程的值吗

以下是为约束引发SQLiteConstraintException时运行时错误的崩溃日志。即使在使用异常时也不会捕获它

E/AndroidRuntime: FATAL EXCEPTION: pool-1-thread-1
    Process: com.mattspriggs.termtest, PID: 23927
    android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 1811 SQLITE_CONSTRAINT_TRIGGER)
        at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native Method)
        at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:784)
        at android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:754)
        at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)
        at android.arch.persistence.db.framework.FrameworkSQLiteStatement.executeUpdateDelete(FrameworkSQLiteStatement.java:45)
        at android.arch.persistence.room.EntityDeletionOrUpdateAdapter.handle(EntityDeletionOrUpdateAdapter.java:70)
        at com.mattspriggs.termtest.database.TermDao_Impl.deleteTerm(TermDao_Impl.java:144)
        at com.mattspriggs.termtest.database.AppRepository$4.run(AppRepository.java:83)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:764)

Room
实际上支持这种行为:

在为子实体定义
外部
键时,您只需将操作
onDelete
设置为
RESTRICT
,而父实体的子实体无法删除

您的子类应如下所示:

@Entity(tableName = "child_table",foreignKeys ={
    @ForeignKey(onDelete = RESTRICT,entity = ParentEntity.class,
    parentColumns = "uid",childColumns = "parentId")},
    indices = {
            @Index("parentId"),
    })
public class ChildEntity {
    @PrimaryKey
    public String id;
    public String parentId;
}
@Entity
public class ParentEntity{
    @PrimaryKey
    public String uid;
}
您的父类如下所示:

@Entity(tableName = "child_table",foreignKeys ={
    @ForeignKey(onDelete = RESTRICT,entity = ParentEntity.class,
    parentColumns = "uid",childColumns = "parentId")},
    indices = {
            @Index("parentId"),
    })
public class ChildEntity {
    @PrimaryKey
    public String id;
    public String parentId;
}
@Entity
public class ParentEntity{
    @PrimaryKey
    public String uid;
}

您可以查看有关如何定义外键的详细信息,添加崩溃日志。谢谢!我知道SQL就是这样,但出于某种原因,我没有意识到它会在Android中得到支持。谢谢你的帮助!轻松解决了我的问题!很乐意帮忙。阅读android文档总是让你知道这些小东西。不幸的是,我无法捕捉到RESTRICT,因为它抛出了一个错误,而不是一个异常。因此,在允许删除之前,我将返回查询子项。不会引发该异常。或者被扔到房间后端处理。您看到的只是正在打印的异常日志。我看到了你的另一个问题。你的答案是错的。这不是一个无法捕获的错误。无法捕获的错误类似于OOM->(内存不足异常),我想我不需要询问您是否尝试使用异常而不是SQLiteConstraintException