【问题标题】:Android room one to many relationshipAndroid机房一对多关系
【发布时间】:2021-04-01 01:04:27
【问题描述】:

我正在尝试建立一对多关系,我已经查看了多篇在线文章和教程,但所有示例都显示一个表与另一个表具有一对多关系。

根据我的要求,我有两个表与另一个表具有一对多关系(请查看下图)

Student 表具有 Class 和 School 表的 FK。大多数示例他们通过班级 - 学生或学校 - 学生来解释一对多关系。

我想做 [Class, School] - 学生。

Core Data 在 iOS 上处理它,但我无法在 Android 上解决这个问题。甚至尝试了 Android 文档中显示的嵌套关系示例,但这不起作用。

【问题讨论】:

    标签: android database android-room one-to-many entity-relationship


    【解决方案1】:

    您的问题/问题尚未明确说明。但是,以下是一个工作示例,演示了根据您的架构提取关系的两种方法。

    • 注意 使用 Class 作为一个类充满了潜在的问题,完全不建议这样做。但是,以下确实使用了该类,并且为了规避某些问题可能无法完全反映您的架构。

    示例代码

    学校实体:-

    @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;
        }
    }
    

    Student 实体(包括外键约束):-

    @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 - 类 StudentWithSchoolWithClass -(使用 @Relation's)

    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;
    }
    

    道接口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,尤其是那个
    • 带有@Relations 的 PJO 具有通过 JOIN 定义的关系

    @Database 类 MyDatabase

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

    最后一个 Activity MainActivity 将一些数据加载到数据库中,然后使用 2 个@Queries 和相应的 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 +
                        "\n\t ID=" + ssc.student.StudentId + " SchoolID=" + ssc.student.SchoolId + " ClassID=" + ssc.student.ClassId +
                        "\n\t\t School Name = " + ssc.school_name +
                        "\n\t\t 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 +
                        "\n\t ID=" + ssc.student.StudentId + " SchoolID=" + ssc.student.SchoolId + " ClassID=" + ssc.student.ClassId +
                        "\n\t\t School Name = " + ssc.schoolList.get(0).SchoolName +
                        "\n\t\t 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
    

    【讨论】:

    • 感谢您的详细回答,我对命名约定不好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    • 1970-01-01
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 2019-07-28
    相关资源
    最近更新 更多