Возврат количества предметов из комнаты DB - PullRequest
1 голос
/ 20 июня 2019

Я пытаюсь предотвратить удаление родителя из БД комнаты, если у него есть дочерние элементы, связанные внешним ключом.

Я работаю над отслеживанием степени. Если есть курсы на срок, термин не может быть удален. Если курсов на срок нет, термин можно удалить. Я пытаюсь получить количество курсов с соответствующим идентификатором термина и использую простое выражение if, чтобы удалить термин, если у него нет курсов, и использовать всплывающее предупреждение, если есть курсы для термина, и дать пользователю указание удалить курсы. до удаления термина.

Из TermEditorActivity.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;
    }

Из AppRepository (вот где я думаю, что вещи рушатся):

public int queryCourses(final int term) {
//        executor.execute(new Runnable() {
//            @Override
//            public void run() {
              return count = courseDb.termDao().queryCourses(term);
//            }
//        });
//            return count;
//        }

or with threading:

 public int queryCourses(final int term) {
        executor.execute(new Runnable() {
            @Override
            public void run() {
              count = courseDb.termDao().queryCourses(term);
            }
        });
            return count;
        }

от TermDAO:

@Query("SELECT COUNT(*) FROM course WHERE term_id = :termIdSelected")
    int queryCourses(int termIdSelected);

Это приводит к ошибке во время выполнения, когда происходит сбой при нажатии кнопки удаления. Концепция проста - используйте идентификатор термина, чтобы запросить базу данных курсов для подсчета курсов с внешним ключом идентификатора термина. Если их нет, удалите термин и вернитесь к списку терминов. Если есть курсы (количество> 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 для ограничения RESTRICT . Он не перехватывается даже при использовании исключения.

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)

1 Ответ

1 голос
/ 20 июня 2019

Room фактически поддерживает это поведение:

при определении клавиши foreign для вашей дочерней сущности вам просто нужно установить действие 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;
}

вы можете проверить здесь для получения дополнительной информации о том, как определить внешний ключ

...