Android房间一对多关系
Android room one to many relationship
我正在尝试建立一对多关系,我已经在线查看了多篇文章和教程,但所有示例都显示一个 table 与另一个 table 具有一对多关系。
在我的要求中,我有两个 table 与另一个 table 具有一对多关系(查看下图)
学生 table 有来自 Class 和学校 table 的 FK。他们通过 Class - 学生或学校 - 学生来解释一对多关系的大多数示例。
我想做 [Class, 学校] - 学生。
Core Data 在 iOS 上处理它,但我无法在 Android 上解决这个问题。甚至尝试了 Android 文档中显示的嵌套关系示例,但这不起作用。
你的issue/problem没有说清楚。但是,以下是一个工作示例,它演示了根据您的模式提取关系的两种方法。
- 注意 使用 Class 作为 class 充满了潜在的问题,根本不推荐。但是,以下内容确实使用了 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;
}
}
Class(一个不明智的名字选择):-
@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 - Class StudentAndSchoolAndClass -(不使用 @Relation
)
class StudentAndSchoolAndClass {
@Embedded
Student student;
String school_name;
String class_name;
}
POJO 方法 2 - Class StudentWithSchoolWithClass -(使用 @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,尤其是
- 带@Relations 的 PJO 具有通过 JOIN 定义的关系
@Database class MyDatabase
@Database(entities = {School.class,Class.class,Student.class},version = 1)
abstract class MyDatabase extends RoomDatabase {
abstract AllDao allDao();
}
最后一个 Activity MainActivity 将一些数据加载到数据库中,然后使用 2 个 @Queries 和各自的提取一些数据POJO class.
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
);
}
}
}
- 注意 在第一个学校和 Class 名字是 class 的成员,而在第二个学校和 Class在列表中。由于学生只有一个 school/class,因此无需遍历列表,因为第一个 element/item (0) 将是列表中唯一的 element/item。
结果
当上面是运行(第一次)数据库是:-
日志包含:-
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
我正在尝试建立一对多关系,我已经在线查看了多篇文章和教程,但所有示例都显示一个 table 与另一个 table 具有一对多关系。
在我的要求中,我有两个 table 与另一个 table 具有一对多关系(查看下图)
学生 table 有来自 Class 和学校 table 的 FK。他们通过 Class - 学生或学校 - 学生来解释一对多关系的大多数示例。
我想做 [Class, 学校] - 学生。
Core Data 在 iOS 上处理它,但我无法在 Android 上解决这个问题。甚至尝试了 Android 文档中显示的嵌套关系示例,但这不起作用。
你的issue/problem没有说清楚。但是,以下是一个工作示例,它演示了根据您的模式提取关系的两种方法。
- 注意 使用 Class 作为 class 充满了潜在的问题,根本不推荐。但是,以下内容确实使用了 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;
}
}
Class(一个不明智的名字选择):-
@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 - Class StudentAndSchoolAndClass -(不使用 @Relation
)
class StudentAndSchoolAndClass {
@Embedded
Student student;
String school_name;
String class_name;
}
POJO 方法 2 - Class StudentWithSchoolWithClass -(使用 @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,尤其是
- 带@Relations 的 PJO 具有通过 JOIN 定义的关系
@Database class MyDatabase
@Database(entities = {School.class,Class.class,Student.class},version = 1)
abstract class MyDatabase extends RoomDatabase {
abstract AllDao allDao();
}
最后一个 Activity MainActivity 将一些数据加载到数据库中,然后使用 2 个 @Queries 和各自的提取一些数据POJO class.
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
);
}
}
}
- 注意 在第一个学校和 Class 名字是 class 的成员,而在第二个学校和 Class在列表中。由于学生只有一个 school/class,因此无需遍历列表,因为第一个 element/item (0) 将是列表中唯一的 element/item。
结果
当上面是运行(第一次)数据库是:-
日志包含:-
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