【问题标题】:Primary and foreign key implementation Java and Android RoomJava和Android Room的主外键实现
【发布时间】:2021-11-19 23:46:44
【问题描述】:

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

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

我现在收到这些错误:

Build Errors

父类: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;
    }

子类: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;
    }

子类: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();

        }

【问题讨论】:

    标签: java android android-room


    【解决方案1】:

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

    让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(评估)- 多(绩效评估),一个评估有多个绩效评估怎么办?删除 1 个 PerformanceAsessment 将删除父评估,然后由于使用 onDelete CASCADE 将删除级联到所有其他 PerformanceAssessments 和 ObjectiveAssessment。删除不会向上传播到父级(这就是使用术语 CASCADE 的原因,因为它暗示向下而不是无论如何)。

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

    您可以引入一个触发器来自动进行这种向上传播,删除任何内容并删除所有内容,如果这是您想要的。

    其他建议

    我的评估和绩效/目标评估是一对一的关系。一项评估只能具有绩效或目标类型。

    这可能是您希望的结果,但是没有什么可以阻止具有多个绩效和/或目标的评估。这可能是也可能不是问题。

    另外,我没有向下转换,而是向上转换了我在应用程序中保存评估的位置。我遇到了外键约束失败(代码 787)并意识到这是因为我在向下转换。我现在唯一的困境是,每当我保存评估时,它只会保存在assessment_table 而不是performance_assessment 或objective_assessment tbl。

    您要做的是插入评估(父级),然后使用父级的 id 插入相关的绩效/目标,并使用评估参考设置评估的值。

    787 是说如果没有assessment_reference 是评估中的assessment_id,您就不能插入孩子(绩效/目标)。

    您可以做什么,很可能适合您的情况:a) 有一个 @Insert long insert(Assessment assessment); 和一个 @Insert long (PerformanceAssessment performanceAssessment)(同样适用于 Objective)

    然后使用(假设dao是@Dao的一个实例)

    并使用

    dao.insert(new PerformanceAssessment(0,"the title", etc,dao.insert(Assessment(....),"the type");
    

    因此,评估是作为插入绩效/目标的一部分添加的,并且评估的 id 用作assessment_reference 值。

    • 注意 @Insert 将只返回一个long,所以你必须把它转换成一个int。我建议将 id 和引用更改为长的。开销(如果有的话)将产生最小的影响。数据库中的存储不受影响,省去了将 long 转换为 int 的麻烦。

    演示

    以下是基于代码的演示,它与您的代码非常接近,但有一些细微的变化。

    1. id 已更改为 long 而不是 int。
    2. autogenerate 已被删除,但 id 将像以前一样生成。 2. 从 SQLite 的角度来看,自动生成所做的只是包含 AUTOINCREMENT 关键字。这实际上是低效的,不推荐。 https://sqlite.org/autoinc.html

    所以代码是:-

    评估

    @Entity(tableName = "assessment_table")
    public class Assessment {
    
        @PrimaryKey /* no need for autogenerate */
        @ColumnInfo(name = "assessment_id")
        /* As not autogenerate then use Long and default to null */
        /* same as autogenerate but without the overheads/inefficiencies */
        private Long assessment_id = null; //Long rather than long so can be null and have id generated.
        private String assessmentName;
        private String assessmentStart;
        private String assessmentEnd;
        private long courseID;
    
        public Assessment(long assessment_id, String assessmentName, String assessmentStart, String assessmentEnd, long courseID) {
            this.assessment_id = assessment_id;
            this.assessmentName = assessmentName;
            this.assessmentStart = assessmentStart;
            this.assessmentEnd = assessmentEnd;
            this.courseID = courseID;
        }
    
        @Ignore
        /* Alternative constructor no need to provide id for inserting */
        public Assessment(String assessmentName, String assessmentStart, String assessmentEnd, long courseID) {
            this.assessmentName = assessmentName;
            this.assessmentStart = assessmentStart;
            this.assessmentEnd = assessmentEnd;
            this.courseID = courseID;
        }
    
        public Long getAssessment_id() {
            return assessment_id;
        }
    
        public void setAssessment_id(Long assessment_id) {
            this.assessment_id = assessment_id;
        }
    
        public String getAssessmentName() {
            return assessmentName;
        }
    
        public void setAssessmentName(String assessmentName) {
            this.assessmentName = assessmentName;
        }
    
        public String getAssessmentStart() {
            return assessmentStart;
        }
    
        public void setAssessmentStart(String assessmentStart) {
            this.assessmentStart = assessmentStart;
        }
    
        public String getAssessmentEnd() {
            return assessmentEnd;
        }
    
        public void setAssessmentEnd(String assessmentEnd) {
            this.assessmentEnd = assessmentEnd;
        }
    
        public long getCourseID() {
            return courseID;
        }
    
        public void setCourseID(long courseID) {
            this.courseID = courseID;
        }
    }
    

    绩效评估

    @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 long assessment_reference;
        private String type;
    
        public PerformanceAssessment(long assessment_id, String assessmentName, String assessmentStart, String assessmentEnd, long courseID, long assessment_reference, String type) {
            super(assessment_id, assessmentName, assessmentStart, assessmentEnd, courseID);
            this.assessment_reference = assessment_reference;
            this.type = type;
        }
    
        @Ignore
        public PerformanceAssessment(String assessmentName, String assessmentStart, String assessmentEnd, long courseID, long assessment_reference, String type) {
            super(assessmentName, assessmentStart, assessmentEnd, courseID);
            this.assessment_reference = assessment_reference;
            this.type = type;
        }
    
        @Override
        public Long getAssessment_id() {
            return super.getAssessment_id();
        }
    
        @Override
        public void setAssessment_id(Long assessment_id) {
            super.setAssessment_id(assessment_id);
        }
    
        @Override
        public String getAssessmentName() {
            return super.getAssessmentName();
        }
    
        @Override
        public void setAssessmentName(String assessmentName) {
            super.setAssessmentName(assessmentName);
        }
    
        @Override
        public String getAssessmentStart() {
            return super.getAssessmentStart();
        }
    
        @Override
        public void setAssessmentStart(String assessmentStart) {
            super.setAssessmentStart(assessmentStart);
        }
    
        @Override
        public String getAssessmentEnd() {
            return super.getAssessmentEnd();
        }
    
        @Override
        public void setAssessmentEnd(String assessmentEnd) {
            super.setAssessmentEnd(assessmentEnd);
        }
    
        @Override
        public long getCourseID() {
            return super.getCourseID();
        }
    
        @Override
        public void setCourseID(long courseID) {
            super.setCourseID(courseID);
        }
    
        public long getAssessment_reference() {
            return assessment_reference;
        }
    
        public void setAssessment_reference(long assessment_reference) {
            this.assessment_reference = assessment_reference;
        }
    
        public String getType() {
            return type;
        }
    
        public void setType(String type) {
            this.type = type;
        }
    }
    

    客观评估

    @Entity(tableName = "objective_assessment", foreignKeys = {
            @ForeignKey(
                    entity = Assessment.class,
                    parentColumns = "assessment_id",
                    childColumns = "assessment_reference",
                    onUpdate = CASCADE,
                    onDelete = CASCADE
            )
    })
    public class ObjectiveAssessment extends Assessment {
    
        private long assessment_reference;
        private String type;
    
        public ObjectiveAssessment(long assessment_id, String assessmentName, String assessmentStart, String assessmentEnd, long courseID, long assessment_reference, String type) {
            super(assessment_id, assessmentName, assessmentStart, assessmentEnd, courseID);
            this.assessment_reference = assessment_reference;
            this.type = type;
        }
    
        @Ignore
        public ObjectiveAssessment(String assessmentName, String assessmentStart, String assessmentEnd, long courseID, long assessment_reference, String type) {
            super(assessmentName, assessmentStart, assessmentEnd, courseID);
            this.assessment_reference = assessment_reference;
            this.type = type;
        }
    
        @Override
        public Long getAssessment_id() {
            return super.getAssessment_id();
        }
    
        @Override
        public void setAssessment_id(Long assessment_id) {
            super.setAssessment_id(assessment_id);
        }
    
        @Override
        public String getAssessmentName() {
            return super.getAssessmentName();
        }
    
        @Override
        public void setAssessmentName(String assessmentName) {
            super.setAssessmentName(assessmentName);
        }
    
        @Override
        public String getAssessmentStart() {
            return super.getAssessmentStart();
        }
    
        @Override
        public void setAssessmentStart(String assessmentStart) {
            super.setAssessmentStart(assessmentStart);
        }
    
        @Override
        public String getAssessmentEnd() {
            return super.getAssessmentEnd();
        }
    
        @Override
        public void setAssessmentEnd(String assessmentEnd) {
            super.setAssessmentEnd(assessmentEnd);
        }
    
        @Override
        public long getCourseID() {
            return super.getCourseID();
        }
    
        @Override
        public void setCourseID(long courseID) {
            super.setCourseID(courseID);
        }
    
        public long getAssessment_reference() {
            return assessment_reference;
        }
    
        public void setAssessment_reference(long assessment_reference) {
            this.assessment_reference = assessment_reference;
        }
    
        public String getType() {
            return type;
        }
    
        public void setType(String type) {
            this.type = type;
        }
    }
    

    POJO 具有嵌入的评估以及通过 @Relation 包含的 Perf 和 Obj(不是理想的,因为只有 1 或非 1 的规则将为空)。所以:-

    AssessmentWithPerformanceAssessmentAndObjectiveAssessment

    class AssessmentWithPerformanceAssessmentAndObjectiveAssessment {
        @Embedded
        Assessment assessment;
        @Relation(
                entity = PerformanceAssessment.class,
                parentColumn = "assessment_id",
                entityColumn = "assessment_reference"
        )
        PerformanceAssessment performanceAssessment;
        @Relation(
                entity = ObjectiveAssessment.class,
                parentColumn = "assessment_id",
                entityColumn = "assessment_reference"
        )
        ObjectiveAssessment objectiveAssessment;
    }
    

    单个 @Dao 注释类:-

    AssessmentDao

    @Dao
    abstract class AssessmentDao {
    
        @Insert
        abstract long insert(Assessment assessment);
        @Insert
        abstract long insert(PerformanceAssessment performanceAssessment);
        @Insert
        abstract long insert(ObjectiveAssessment objectiveAssessment);
        /*
            use to check if an Assessment has any children
         */
        @Query("WITH cte_counts(counter) AS (" +
                "SELECT count(*) > 0 FROM performance_assessment WHERE assessment_reference=:assessment_id " +
                "UNION ALL SELECT count(*) FROM objective_assessment WHERE assessment_reference=:assessment_id" +
                ")" +
                "SELECT sum(counter) > 0 FROM cte_counts")
        abstract boolean hasChildAlready(long assessment_id);
    
        @Transaction
        @Query("SELECT * FROM assessment_table WHERE assessment_id=:assessment_id")
        abstract AssessmentWithPerformanceAssessmentAndObjectiveAssessment getAssessmentWithPerformanceAssessmentOrObjectiveAssessmentById(long assessment_id);
    
        @Transaction
        @Query("SELECT * FROM assessment_table")
        abstract List<AssessmentWithPerformanceAssessmentAndObjectiveAssessment> getAllAssessmentsWithPerformanceAssessmentOrObjectiveAssessmentById();
    }
    
    • 注意抽象类而不是接口(虽然可能是接口)

    @Database 注释类

    评估数据库

    @Database(entities = {Assessment.class,PerformanceAssessment.class,ObjectiveAssessment.class},version =1)
    abstract class AssessmentDatabase extends RoomDatabase {
        abstract AssessmentDao getAssessmentDao();
    
        private static volatile AssessmentDatabase instance = null;
        static AssessmentDatabase getInstance(Context context) {
            if (instance == null) {
                instance = Room.databaseBuilder(context,AssessmentDatabase.class,"assessment.db")
                        .allowMainThreadQueries()
                        .build();
            }
            return instance;
        }
    }
    
    • 注意为了方便和简洁,允许在主线程上运行。

    终于在一个Activity中实际使用了上面的内容:-

    public class MainActivity extends AppCompatActivity {
    
        AssessmentDatabase db;
        AssessmentDao dao;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            db = AssessmentDatabase.getInstance(this);
            dao = db.getAssessmentDao();
    
            /* Various Inserts */
            long loneAssessment = dao.insert(
                    new Assessment(
                    "Lone Assessment with no children",
                    "2021-01-15",
                    "2021-03-15",
                    0L
                    )
            );
            /* id will be 100, subsequent id's if generated will be 101,102......*/
            long a1 = dao.insert(new Assessment(100,"A1","2022-01-01","2022,03-01",10));
            long p1 = dao.insert(new PerformanceAssessment("P1","2022-01-31","2022-01-31",10,a1,"X"));
    
            /* back to using generated Assessment id */
            long a2 = dao.insert(new Assessment("A1","2022-01-01","2022-03-01",11));
            long p2 = dao.insert(new ObjectiveAssessment("O1","2022-01-31","2022-01-31",11,a2,"Y"));
    
            /* Build the Assessment and ObjectiveAssessment ready for  insert SEE WARNING */
            Assessment a10 = new Assessment("A10","2022-01-01","2022-03-01",20);
            ObjectiveAssessment o10 = new ObjectiveAssessment("O10","2022-01-31","2022-01-31",a10.getCourseID(),0,"Z");
            /* WARNING assessment_reference WILL NOT BE ANY GOOD (will be 0) */
            long a10id = dao.insert(a10);
            o10.setAssessment_reference(a10id); /*<<<<<<<<<< NOW assessment_reference should be good */
            dao.insert(o10);
    
            /* Both together */
            dao.insert(
                    new PerformanceAssessment("P20","2022-05-07","2022-05-07",11,
                            /* get the Assessment ID from the insert of the Assessment */
                            dao.insert(
                                    new Assessment("A20","2022-04-01","2022-06-17",21)
                            ),
                            "ZZ"
                    )
            );
    
            /* Extract all the Assessments with their children (if any)*/
            for(AssessmentWithPerformanceAssessmentAndObjectiveAssessment awpoo: dao.getAllAssessmentsWithPerformanceAssessmentOrObjectiveAssessmentById()) {
                Log.d("DBINFO","Assessment is " + awpoo.assessment.getAssessmentName() + " id is " + awpoo.assessment.getAssessment_id() + " etc....");
                /* need to check if the the performanceassessment is null - it will be if there isn't one */
                if (awpoo.performanceAssessment != null) {
                    Log.d("DBINFO","\t\tPerformanceAssessment = " + awpoo.performanceAssessment.getAssessmentName() +
                            " id is "+ awpoo.performanceAssessment.getAssessment_id() +
                            " references Asessment with id " + awpoo.performanceAssessment.getAssessment_reference());
                } else {
                    Log.d("DBINFO","\t\tNo PerformanceAssessment.");
                }
                /* null check see performance assessment check above */
                if (awpoo.objectiveAssessment != null) {
                    Log.d("DBINFO","\t\tObjectiveAssessment = " + awpoo.objectiveAssessment.getAssessmentName() +
                            " id is "+ awpoo.objectiveAssessment.getAssessment_id() +
                            " references Asessment with id " + awpoo.objectiveAssessment.getAssessment_reference());
                } else {
                    Log.d("DBINFO","\t\tNo ObjectiveAssessment.");
                }
            }
        }
    }
    

    运行时(第一次,如果运行两次将失败,因为 id 使用 100)日志显示:-

    D/DBINFO: Assessment is Lone Assessment with no children id is 1 etc....
    D/DBINFO:       No PerformanceAssessment.
    D/DBINFO:       No ObjectiveAssessment.
    D/DBINFO: Assessment is A1 id is 100 etc....
    D/DBINFO:       PerformanceAssessment = P1 id is 1 references Asessment with id 100
    D/DBINFO:       No ObjectiveAssessment.
    D/DBINFO: Assessment is A1 id is 101 etc....
    D/DBINFO:       No PerformanceAssessment.
    D/DBINFO:       ObjectiveAssessment = O1 id is 1 references Asessment with id 101
    D/DBINFO: Assessment is A10 id is 102 etc....
    D/DBINFO:       No PerformanceAssessment.
    D/DBINFO:       ObjectiveAssessment = O10 id is 2 references Asessment with id 102
    D/DBINFO: Assessment is A20 id is 103 etc....
    D/DBINFO:       PerformanceAssessment = P20 id is 2 references Asessment with id 103
    D/DBINFO:       No ObjectiveAssessment.
    

    使用 App Inspection 然后数据库看起来像:-

    • 查看 Assessment_id 为 2(它是唯一的行标识符)的 PerformanceAssessment 的assessment_reference 值为 103。这表示assessment_id 为 103 的评估是父项(或者此 PerformanceAssessment 与具有103 的评估 ID)。

    【讨论】:

    • 感谢您的帮助。我听从了你的建议并摆脱了错误。我的评估和绩效/目标评估是一对一的关系。一项评估只能具有绩效或目标类型。此外,我没有向下转换,而是向上转换了我在应用程序中保存评估的位置。我遇到了外键约束失败(代码 787)并意识到这是因为我在向下转换。我现在唯一的困境是,每当我保存评估时,它只会保存在assessment_table 而不是performance_assessment 或objective_assessment tbl。
    • @JayM 添加了一些额外的注释以回应您的 cmets。
    • 我对assessment_reference 变量有点困惑。在这种情况下,它是否会被视为 PerformanceAssessment 的 id?如果是这样,我需要自动递增吗?当我声明 PerformanceAssessment 时,我是这样做的:Assessment performanceAssessment = (Assessment) new PerformanceAssessment(0, assessmentTitle, assessmentStart, assessmentEnd, currentCourseID, 0, selectedString); 在这种情况下,assessment_id 将自动递增,但在此使用的assessment_reference 如何。它不应该自动递增吗? Android对我来说是全新的。感谢您的帮助。
    • 没有自动递增的assessment_reference 它必须是现有Assessment 的assessment_id。 这就是我的父母是谁。 如果不是(尝试插入时)现有评估的评估 ID,则为 787,因为规则(又名外键)已被破坏。很快就会发布一个工作示例的代码。
    • 这太不可思议了。非常感谢你的帮助。我感谢所有的努力。干杯!
    猜你喜欢
    • 2019-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多