Android-комната отношения «один ко многим»

#android #database #android-room #one-to-many #entity-relationship

Вопрос:

Я пытаюсь установить отношение «один ко многим», я проверил несколько статей и учебных пособий в Интернете, но все примеры показывают, что одна таблица имеет отношение «один ко многим» с другой таблицей.

В моем требовании у меня есть две таблицы, имеющие отношение «один ко многим» к другой таблице (см. диаграмму ниже).

В таблице учащихся есть данные из класса и школьного стола. В большинстве примеров они объясняют отношения «один ко многим» либо по классу, либо по школьнику.

Я хочу заниматься [Классом, Школой] — Учеником.

Основные данные заботятся об этом на iOS, но я не могу разобраться в этом на Android. Даже попробовал пример вложенных отношений, показанный в документации Android, но это не работает.

введите описание изображения здесь

Ответ №1:

Ваша проблема/проблема не была четко сформулирована. Однако ниже приведен рабочий пример, демонстрирующий два способа извлечения связей на основе вашей схемы.

  • Обратите внимание, что использование класса как класса чревато потенциальными проблемами, и это вообще не рекомендуется. Тем не менее, ниже приведен класс, и для обхода некоторых проблем он может не полностью отражать вашу схему.

Пример кода

Школьная организация :-

 @Entity(tableName = "_school")
class School {
    @PrimaryKey
    @ColumnInfo(name = "school_id")
    Long Schoolid;
    @NonNull
    @ColumnInfo(name = "school_name")
    String SchoolName;

    School(){}

    @Ignore
    School(String schoolName) {
        this.SchoolName = schoolName;
    }
}
 

Класс (неразумный выбор названия) :-

 @Entity(tableName = "_class")
class Class {
    @PrimaryKey
    @ColumnInfo(name = "class_id")
    Long ClassId;
    @NonNull
    @ColumnInfo(name = "class_name")
    String ClassName;

    Class(){}

    @Ignore
    Class(String className) {
        this.ClassName = className;
    }
}
 

Сущность учащегося ( включая ограничения внешнего ключа):-

 @Entity(
        tableName = "_student", foreignKeys = {
        @ForeignKey(
                entity = School.class,
                parentColumns = {"school_id"},
                childColumns = {"school_id"},
                onDelete = ForeignKey.CASCADE,
                onUpdate = ForeignKey.CASCADE
        ),
        @ForeignKey(
                entity = Class.class,
                parentColumns = {"class_id"},
                childColumns = {"class_id"},
                onDelete = ForeignKey.CASCADE,
                onUpdate = ForeignKey.CASCADE
        )
        }
)
class Student {
    @PrimaryKey
    @ColumnInfo(name = "student_id")
    Long StudentId;
    @ColumnInfo(name = "Student_name")
    String StudentName;
    @ColumnInfo(name = "school_id", index = true)
    Long SchoolId;
    @ColumnInfo(name = "class_id", index = true)
    Long ClassId;

    Student(){}

    @Ignore
    Student(String studentName, long schoolId, long classId) {
        this.StudentName = studentName;
        this.SchoolId = schoolId;
        this.ClassId = classId;
    }
}
 

Метод POJO 1 — Класс StudentAndSchoolAndClass — (НЕ ИСПОЛЬЗУЕТСЯ @Relation )

 class StudentAndSchoolAndClass {

    @Embedded
    Student student;
    String school_name;
    String class_name;
}
 

Метод POJO 2 — Класс Учащийся со школой с классом @Relation — (Использует)

 class StudentWithSchoolWithClass {

    @Embedded
    Student student;

    @Relation(entity = School.class,parentColumn = "school_id", entityColumn = "school_id")
    List<School> schoolList;
    @Relation(entity = Class.class,parentColumn = "class_id",entityColumn = "class_id")
    List<Class> classList;
}
 

Интерфейс Dao AllDao

 @Dao
interface AllDao {

    @Insert
    Long insertSchool(School s);
    @Insert
    Long insertClass(Class c);
    @Insert
    Long insertStudent(Student s);
    @Query("SELECT * FROM _school")
    List<School> getAllSchools();
    @Query("SELECT * FROM _school WHERE school_id = :school_id ")
    School getSchoolById(Long school_id);
    @Query("SELECT * FROM _class")
    List<Class> getAllClasses();
    @Query("SELECT * FROM _class WHERE class_id = :class_id")
    Class getClassById(Long class_id);
    @Query("SELECT * FROM _student JOIN _school ON _school.school_id = _student.school_id JOIN _class ON _class.class_id = _student.class_id")
    List<StudentAndSchoolAndClass> getStudentAndSchoolAndClass();
    @Query("SELECT * FROM _student")
    List<StudentWithSchoolWithClass> getStudentWithSchoolWithClass();

}
 
  • Обратите внимание, что в двух последних запросах используется соответствующий POJO, и особенно это
  • PJO с @отношениями имеет отношения, определенные с помощью СОЕДИНЕНИЯ

База данных класса @Database MyDatabase

 @Database(entities = {School.class,Class.class,Student.class},version = 1)
abstract class MyDatabase extends RoomDatabase {
    abstract AllDao allDao();
}
 

Наконец, основное действие, которое загружает некоторые данные в базу данных, а затем извлекает некоторые данные с помощью 2 @запросов и соответствующего класса POJO.

 public class MainActivity extends AppCompatActivity {

    MyDatabase db;
    AllDao allDao;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Build the MyDatabase instance
        db = Room.databaseBuilder(this,MyDatabase.class,"mydb")
                .allowMainThreadQueries()
                .build();
        // Build the allDao instance
        allDao = db.allDao();

        // Create some school objects
        School[] s_array = {new School("School1"),
                new School("School2"),
                new School("School3")
        };
        // Insert the Schools into the database
        for (School s: s_array) {
            allDao.insertSchool(s);
        }

        // Create some Class objects
        Class[] c_array = {
                new Class("Class1"),
                new Class("Class2"),
                new Class("Class3")
        };
        // Insert the classes
        for (Class c: c_array) {
            allDao.insertClass(c);
        }

        // Create some Student Objects
        Student[] st_array = {
                new Student("Fred",3,3), new Student("Mary",1,2)
        };
        //Insert the Students
        for(Student st: st_array) {
            allDao.insertStudent(st);
        }

        // Get the Students with the School and Class information using POJO 1 (realtionship via joins)
        List<StudentAndSchoolAndClass> sasac = allDao.getStudentAndSchoolAndClass();
        // Log the data
        for(StudentAndSchoolAndClass ssc: sasac) {
            Log.d("STUDENTINFO1","Student Name = "   ssc.student.StudentName  
                    "nt ID="   ssc.student.StudentId   " SchoolID="   ssc.student.SchoolId   " ClassID="   ssc.student.ClassId  
                    "ntt School Name = "   ssc.school_name  
                    "ntt Class Name = "   ssc.class_name
                    );
        }
        // Get the Students with the School and Class information using POJO 2 (with @Relation's)
        List<StudentWithSchoolWithClass> swswc = allDao.getStudentWithSchoolWithClass();
        for(StudentWithSchoolWithClass ssc: swswc) {
            Log.d("STUDENTINFO2","Student Name = "   ssc.student.StudentName  
                    "nt ID="   ssc.student.StudentId   " SchoolID="   ssc.student.SchoolId   " ClassID="   ssc.student.ClassId  
                    "ntt School Name = "   ssc.schoolList.get(0).SchoolName  
                    "ntt Class Name = "   ssc.classList.get(0).ClassName
            );
        }
    }
}
 
  • Обратите внимание, что в первом случае название Школы и класса являются членами класса, в то время как для второго Школа и Класс находятся в Списке. Поскольку у Учащегося будет только одна школа/класс, нет необходимости просматривать список, так как первый элемент/элемент (0) будет единственным элементом/элементом в списке.

Результаты

Когда вышеописанное выполняется (в первый раз) , база данных :-

введите описание изображения здесь

Журнал содержит :-

 2021-04-01 22:09:51.977 D/STUDENTINFO1: Student Name = Fred
         ID=1 SchoolID=3 ClassID=3
             School Name = School3
             Class Name = Class3
2021-04-01 22:09:51.977 D/STUDENTINFO1: Student Name = Mary
         ID=2 SchoolID=1 ClassID=2
             School Name = School1
             Class Name = Class2


2021-04-01 22:09:51.982 D/STUDENTINFO2: Student Name = Fred
         ID=1 SchoolID=3 ClassID=3
             School Name = School3
             Class Name = Class3
2021-04-01 22:09:51.982 D/STUDENTINFO2: Student Name = Mary
         ID=2 SchoolID=1 ClassID=2
             School Name = School1
             Class Name = Class2
 

Комментарии:

1. Спасибо за подробный ответ и мою вину за соглашение об именах.