繁体   English   中英

主外键实现Java和Android机房

[英]Primary and foreign key implementation Java and Android Room

这是我第一次在 StackOverflow 中提出问题,如果我没有正确或以某种方式提出问题,请原谅我。

我有来自父 class 评估的两个子类(PerformanceAssessment 和 ObjectiveAssessment)。 我能够成功地为我的学校项目的多态性部分要求进行向下转换,并且能够在向下转换后将父母和孩子的实例保存到他们适当的数据库中(我有一个评估表、性能评估表和目标评估表)。 但是,我现在遇到了 Android Room 数据库问题。 我意识到我需要实现外键才能正确执行 CRUD 操作。 如何调整我的父类和子类代码并添加适当的注释以正确实现外键和主键? 我需要为每个 class 自动生成主键:父(评估)和两个子(性能评估和目标评估)。 但是我还需要利用子主键作为父数据库的外键,这样当我删除性能/目标评估的实例时,我也可以在向下转换时删除评估实例。 我发现很少有关于此的有用信息。 提前致谢。

我现在收到这些错误:

构建错误

父 Class:Assessment.java

@Entity(tableName = "assessment_table")
public class Assessment {

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "assessment_id")
    private final int assessment_id;

    private String assessmentName;
    private String assessmentStart;
    private String assessmentEnd;
    private int courseID;

    public Assessment(int assessment_id, String assessmentName, String assessmentStart, String assessmentEnd, int courseID) {
        this.assessment_id = assessment_id;
        this.assessmentName = assessmentName;
        this.assessmentStart = assessmentStart;
        this.assessmentEnd = assessmentEnd;
        this.courseID = courseID;
    }

儿童 class:PerformanceAssessment.java

@Entity(tableName = "performance_assessment", foreignKeys = {
        @ForeignKey(
                entity = Assessment.class,
                parentColumns = "assessment_id",
                childColumns = "performance_id",
                onUpdate = CASCADE,
                onDelete = CASCADE
        )
})
public class PerformanceAssessment extends Assessment{

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "performance_id")
    private int performanceID;
    private String type;

    public PerformanceAssessment(int assessment_id, String assessmentName, String assessmentStart, String assessmentEnd, int courseID, int performanceID, String type) {
        super(assessment_id, assessmentName, assessmentStart, assessmentEnd, courseID);
        this.performanceID = performanceID;
        this.type = type;
    }

儿童 class:ObjectiveAssessment.java

@Entity(tableName = "objective_assessment", foreignKeys = {
        @ForeignKey(
                entity = Assessment.class,
                parentColumns = "assessment_id",
                childColumns = "objective_id",
                onUpdate = CASCADE,
                onDelete = CASCADE
        )
})
public class ObjectiveAssessment extends Assessment{

    @PrimaryKey(autoGenerate = true)
    @ColumnInfo(name = "objective_id")
    private int objective_ID;
    private String type;

    public ObjectiveAssessment(int assessmentID, String assessmentName, String assessmentStart, String assessmentEnd, int courseID, int objective_ID, String type) {
        super(assessmentID, assessmentName, assessmentStart, assessmentEnd, courseID);
        this.objective_ID = objective_ID;
        this.type = type;
    }

这是我在应用程序中添加新评估的部分:

public void saveAssessment(View view) {

        assessmentTitle = editName.getText().toString();
        assessmentStart = editStart.getText().toString();
        assessmentEnd = editEnd.getText().toString();

        //Check if fields are empty:
        if (assessmentTitle.isEmpty() || assessmentStart.isEmpty() || assessmentEnd.isEmpty()) {

            Toast.makeText(AddAssessmentScreen.this, "Fill out required fields.", Toast.LENGTH_LONG).show();
            return;

        }
        else {

            //Check assessment type selected (used Downcasting for polymorphism):

            if (assessment_type == true) {
                Assessment performanceAssessment = new PerformanceAssessment(0, assessmentTitle, assessmentStart, assessmentEnd, currentCourseID, 0, selectedString);
                PerformanceAssessment castedPerformance = (PerformanceAssessment) performanceAssessment;
                //Insert assessment to database performance_assessment table (Performance child type):
                repository.insert(castedPerformance);
                Repository addToAssessment = new Repository(getApplication());
                //Insert assessment to database assessment_table (Assessment parent type):
                addToAssessment.insert(performanceAssessment);

            }
            else {
                Assessment objectiveAssessment = new ObjectiveAssessment(0,assessmentTitle, assessmentStart, assessmentEnd, currentCourseID, 0, selectedString);
                ObjectiveAssessment castedObjective = (ObjectiveAssessment) objectiveAssessment;
                //Insert assessment to database objective_assessment table (Objective child type):
                repository.insert(castedObjective);
                Repository addToAssessment = new Repository(getApplication());
                //Insert assessment to database assessment_table (Assessment parent type):
                addToAssessment.insert(objectiveAssessment);
            }

            Toast.makeText(AddAssessmentScreen.this, "New assessment added. Refresh previous screen.", Toast.LENGTH_LONG).show();

        }

如何调整我的父类和子类代码并添加适当的注释以正确实现外键和主键?

让assessment_id 始终是主键,即不要在子类中对其进行编码,然后在子类中拥有一个用于引用/映射/关联的字段。

所以 PerformanceAssessment 可以是:-

@Entity(tableName = "performance_assessment", foreignKeys = {
        @ForeignKey(
                entity = Assessment.class,
                parentColumns = "assessment_id",
                childColumns = "assessment_reference",
                onUpdate = CASCADE,
                onDelete = CASCADE
        )
})
public class PerformanceAssessment extends Assessment {

    private int assessment_reference; //<<<<<<<<<
    private String type;

    public PerformanceAssessment(int assessment_id, String assessmentName, String assessmentStart, String assessmentEnd, int courseID, int assessment_reference, String type) {
        super(assessment_id, assessmentName, assessmentStart, assessmentEnd, courseID);
        this.assessment_reference = assessment_reference;
        this.type = type;
    }
    ....

并且所有编译和基础表都将使用以下方式构建:-

    _db.execSQL("CREATE TABLE IF NOT EXISTS `assessment_table` (`assessment_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `assessmentName` TEXT, `assessmentStart` TEXT, `assessmentEnd` TEXT, `courseID` INTEGER NOT NULL)");
    _db.execSQL("CREATE TABLE IF NOT EXISTS `performance_assessment` (`assessment_reference` INTEGER NOT NULL, `type` TEXT, `assessment_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `assessmentName` TEXT, `assessmentStart` TEXT, `assessmentEnd` TEXT, `courseID` INTEGER NOT NULL, FOREIGN KEY(`assessment_reference`) REFERENCES `assessment_table`(`assessment_id`) ON UPDATE CASCADE ON DELETE CASCADE )");
  • ObjectiveAssessment 显然类似。

但是我还需要利用子主键作为父数据库的外键,这样当我删除性能/目标评估的实例时,我也可以在向下转换时删除评估实例。

如果使用 1 (Assessment) - Many (PerformanceAssessments) 是可能的,一个评估有多个 PerformanceAssessments 怎么办? 删除 1 个 PerformanceAsessment 将删除父评估,然后由于使用onDelete CASCADE将删除级联到所有其他 PerformanceAssessment 和 ObjectiveAssessment。 删除不会传播到父级(这就是使用术语 CASCADE 的原因,因为它暗示向下而不是无论如何)。

例如,您有一个包含 4 个 PerformanceAssessments 的评估,假设 3 个 ObjectiveAssessments 其中一个 PerformanceAssessments 被错误地添加了。 是否必须删除所有内容并重新输入以更正 1 错误的绩效评估。

如果这是你想要的,你可以引入一个触发器来自动化这种向上传播,删除任何东西并删除所有东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM