- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试对以下内容进行建模:
学生可以参加考试并获得成绩。
应该可以将同一个成绩实体分配给多个学生。
成绩存储在 map 中(在“考试”类中),其注释如下:
@ManyToMany
@MapKeyClass(value = Person.class)
@JoinTable(name = "t1")
private Map<Person, Grade> grades;
JPA 创建以下连接表:
T1:
EXAM_ID: stores the id of the exam, is part of the primary key
GRADES_ID: stores the id of the grade, is part of the primary key
GRADES_KEY: stores the id of the student, is not part of the primary key
然而,我期望的表格会有一个包含学生和考试的主键。
我现在面临的问题是当我尝试以下操作时:
grades.put(student1, grade1);
grades.put(student2, grade1);
...我会得到一个异常,告诉我我违反了数据库约束。
我如何正确保留此映射?
我使用 eclipselink 2.6.0 作为 JPA 提供程序。该应用程序在带有 derby 数据库的 glassfish 服务器上运行。
感谢您的阅读,祝您有愉快的一天:)
更新:
这些是创建数据库的 SQL 查询、eclipselink 调用:
...
CREATE TABLE EXAM_GRADE (Exam_ID BIGINT NOT NULL, grades_ID BIGINT NOT NULL, grades_KEY BIGINT, PRIMARY KEY (Exam_ID, grades_ID))
...
ALTER TABLE EXAM_GRADE ADD CONSTRAINT EXAMGRADEgrades_ID FOREIGN KEY (grades_ID) REFERENCES GRADE (ID)
ALTER TABLE EXAM_GRADE ADD CONSTRAINT EXAMGRADEgradesKEY FOREIGN KEY (grades_KEY) REFERENCES PERSON (ID)
ALTER TABLE EXAM_GRADE ADD CONSTRAINT EXAM_GRADE_Exam_ID FOREIGN KEY (Exam_ID) REFERENCES EXAM (ID)
...
最佳答案
好吧,我们这里遇到了几个问题:我在 Hibernate 上试过了,但得到的结果与你不同。我认为 Hibernate 做的是正确的,因此我对更新的第一个回答。
首先,您显示的代码不应产生您所获得的结果。当您声称 GRADES_ID
是 join table
中的 primary key
的一部分时,这不应该是真的。当我运行该示例时,我得到了 primary key (Exam_id, grades_KEY)
。
其次,您的 grades
字段中应该有一个 OneToMany
关系,而不是一个 ManyToMany
关系。当您为两个学生插入相同的成绩时,具有 ManyToMany
关系不应导致约束冲突
。当你有一个 OneToMany
关系时,将创建一个 constraint
for unique (grades_id)
,这确实会阻止你插入相同的成绩两个学生:
grades.put(student1, grade1);
grades.put(student2, grade1);
具有约束
是可取的,因为它可以防止一个学生的成绩也分配给另一个学生的编码错误。
当您考虑关系时,请考虑实体
之间的关系。在这种情况下,您有一个 Exam
和许多 Student
,因此您应该有一个 OneToMany
。
最后,MapKeyClass
是多余的,没有充分的理由自己命名您的连接表
,尤其是t1
。
你们的关系应该很简单:
@OneToMany(fetch=FetchType.EAGER)
private Map<Student, Grade> grades;
当您创建考试
时,请确保为每个学生保存唯一的成绩:
public void testCreateExam() {
Student student1 = new Student("Karl");
Grade grade1 = new Grade(85);
Student student2 = new Student("Debbie");
Grade grade2 = new Grade(90);
Map<Student, Grade> grades = new HashMap<Student, Grade>();
grades.put(student1, grade1);
grades.put(student2, grade2);
examService.createExam("Biology", grades);
}
并确保您首先坚持每个 Student
和 Grade
(或制定适当的逻辑):
public Exam createExam(String name, Map<Student, Grade> grades) {
for(Student student: grades.keySet()) {
em.persist(student);
Grade grade = grades.get(student);
em.persist(grade);
}
Exam exam = new Exam(name);
exam.setGrades(grades);
em.persist(exam);
return exam;
}
更新:
我查看了 EclipseLink 2.6。哇,完全是 FUBAR。首先,它甚至不允许我用 OneToMany
注释 Map,这是完全错误的。其次,它处理 ManyToMany
的方式与我描述的 Hibernate 处理 OneToMany
的方式完全相同。所以,我得到了 Eclipselink
版本来像 Hibernate
使用 ManyToMany
那样工作,但是我必须生成 Schema 脚本,通过手,并使用它们来创建数据库。几乎不是开发代码的好方法。
// Change the primary key to be the Exam_Id and the grades_KEY
CREATE TABLE EXAM_GRADE (Exam_ID BIGINT NOT NULL, grades_ID BIGINT NOT NULL, grades_KEY BIGINT, PRIMARY KEY (Exam_ID, grades_KEY))
// removed the constraint for grades_ID references GRADE (ID)
ALTER TABLE EXAM_GRADE ADD CONSTRAINT EXAMGRADEgradesKEY FOREIGN KEY (grades_KEY) REFERENCES PERSON (ID)
ALTER TABLE EXAM_GRADE ADD CONSTRAINT EXAM_GRADE_Exam_ID FOREIGN KEY (Exam_ID) REFERENCES EXAM (ID)
在进行这些更改后,我能够为不同的 Student
编写和读取相同的 Grade
。这些模式脚本现在正是 Hibernate 生成它们的方式。我认为在 Eclipselink 上发生了一些有趣的事情,提交一个关于这个的错误是个好主意。另外,请注意,虽然您可能想为不同的学生分配相同的分数,但这在问题领域没有意义,但这当然是我的拙见。我意识到 Java Map
将能够让不同的 keys
引用相同的 value
,所以对于某些问题来说这当然是一个可以想象的要求, Ecpliselink
似乎无法处理。
关于java - JPA:从实体到实体的 HashMap 在连接表中获取错误的主键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35380705/
我有不同的结构,它们都包含一个 HashMap与 String作为键,但具有不同的值类型。例如,一个结构有一个类型为 HashMap 的成员, 另一个将有一个 HashMap 类型的成员, 等等。 我
我想制作一个包含学生姓名和科目的板,每个学生在每个科目中都有一个成绩(或者没有..他可以离开考试而不写,然后他的案子将是空的)。我只想使用 HashMap。我的意思是,它会是这样的: HashMap>
是否有内存和速度高效的方法来在 HashMap 中动态存储唯一键:值对? key 保证是唯一的,但它们的数量经常变化。插入和删除必须很快。 我所做的是包含有符号距离场的八叉树(非线性/完整)。八叉树经
有谁知道为什么选择通过 LinkedList 而不是另一个 Hashmap 来实现 HashMap 的存储桶。如果桶本身变成了 HashMap,那么 contains 或 get 的时间复杂度似乎是
我想创建一个具有嵌套结构的 HashMap,就像这个复杂的示例: { type: boy name: Phineas father: type: man
这个问题在这里已经有了答案: How do I create a global, mutable singleton? (7 个答案) 关闭 7 年前。 我想要一个可扩展的字典,将 Object 与
HashMap> hm = new HashMap>(); hm.put("Title1","Key1"); for(int i=0;i hm1 = new H
我必须修改当前代码以适应 Spring MVC。我有 HashMap hashmap = new HashMap(); request.setAttribute("dslrErrors", hashm
我正在尝试进行一些错误捕获。 错误应该检查数组的长度是否小于 2,并检查 HashMap 是否包含用户输入的键。 捕获的错误必须仅使用 if 语句,并且必须使用 .length() 方法,并且必须使用
在 stackoverflow 上提出另一个问题后,(Java- Why this program not throwing concurrent Modification exception)我开始
我有两个类,想使用 org.dozer.Mapper( http://dozer.sourceforge.net/ ) 将 Female 对象的属性映射到 Male 对象。 第一类是: public
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be
是否有任何方法可以检查 HashMap 是否包含一组特定的键(这些键是在数组中给出的)。当我尝试类似下面的代码时,它返回 false。 map.containsKey(arrayOf("2018-01
跟进我的问题:How To Access hash maps key when the key is an object 我想尝试这样的事情:webSearchHash.put(xfile.getPa
我有一个可扩展的 ListView ,对于每个 child ,我需要有 4 个“额外”或字符串或其他名称来调用它:- 子标题- 描述- 链接1- 链接2 跟着教程,创建 ListView 、不同的 p
我想确保这是正确的,因为如果不正确,它可能会破坏我的应用程序。 我有这个: private static HashMap> balance = new HashMap<>(); 如果我得到这样的值:
我想做以下事情: 为某个键查找Vec,并将其存储以备后用。 如果它不存在,则为键创建一个空的 Vec,但仍将其保存在变量中。 如何有效地做到这一点?自然地,我认为我可以使用 match: use st
我想做以下事情: 为某个键查找Vec,并将其存储以备后用。 如果它不存在,则为键创建一个空的 Vec,但仍将其保存在变量中。 如何有效地做到这一点?自然地,我认为我可以使用 match: use st
我想做以下事情: 为某个键查找Vec,并将其存储以备后用。 如果它不存在,则为键创建一个空的 Vec,但仍将其保存在变量中。 如何有效地做到这一点?自然地,我认为我可以使用 match: use st
我想做以下事情: 为某个键查找Vec,并将其存储以备后用。 如果它不存在,则为键创建一个空的 Vec,但仍将其保存在变量中。 如何有效地做到这一点?自然地,我认为我可以使用 match: use st
我是一名优秀的程序员,十分优秀!