Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 组合键的组合键_Java_Mysql_Sql_Hibernate_Jpa - Fatal编程技术网

Java 组合键的组合键

Java 组合键的组合键,java,mysql,sql,hibernate,jpa,Java,Mysql,Sql,Hibernate,Jpa,我试图了解我正在创建的数据模型采用的方法。我有两个最初使用复合键创建的表。我现在添加了第三个表,它是前两个表的联接表,这将产生一个由三个字段和两个外键组成的复合键,每个外键有两个字段。这可能会出现在MySQL中,并与某种Java持久性框架一起使用。我一直喜欢使用复合关键点,因为这似乎是一种更自然的数据表示方式,但我想确保我不会让自己在以后的世界中受到伤害。我应该继续使用上面提到的方法还是在表上创建一些自动递增的ID?如果多对多是纯关系(本身没有属性),并且永远不会在自身上被引用,那么就使用复合键

我试图了解我正在创建的数据模型采用的方法。我有两个最初使用复合键创建的表。我现在添加了第三个表,它是前两个表的联接表,这将产生一个由三个字段和两个外键组成的复合键,每个外键有两个字段。这可能会出现在MySQL中,并与某种Java持久性框架一起使用。我一直喜欢使用复合关键点,因为这似乎是一种更自然的数据表示方式,但我想确保我不会让自己在以后的世界中受到伤害。我应该继续使用上面提到的方法还是在表上创建一些自动递增的ID?

如果多对多是纯关系(本身没有属性),并且永远不会在自身上被引用,那么就使用复合键


如果它可能有自己的属性或被引用(如实例化为类),您可能需要一个代理键,因为许多
ORM
要求
id
为单个整数。

Hibernate建议使用纯技术、自动生成的非复合键(纯联接表除外)。还有很好的理由,国际海事组织

使用复合关键点时,映射将更加困难。由于更复杂的指标,性能将降低。常规编程将更加困难,因为您需要两个或三个long(例如,考虑URL和表单,您必须在URL/表单中放置两个或三个参数/隐藏字段),而不是用一个long来识别给定的实体


当然,如果这些键是功能性的,那就更糟了,因为你需要在某个时候更改主键的某个部分,这将迫使您更新对此主键的所有引用。

连接表的代理键在约束与外键的深层关系时有一个巨大的缺陷。我们需要一个6张桌子的设置来演示它

基本表:

CREATE TABLE semester (semester_id INTEGER PRIMARY KEY, semester_name VARCHAR(40));
CREATE TABLE student  (student_id  INTEGER PRIMARY KEY, student_name  VARCHAR(40));
CREATE TABLE subject  (subject_id  INTEGER PRIMARY KEY, subject_name  VARCHAR(40));
那么让我们把它们连接起来:

CREATE TABLE enrollment (
  enrollment_id INTEGER PRIMARY KEY,
  semester_id INTEGER NOT NULL,
  student_id INTEGER NOT NULL,
  room_number INTEGER,
  FOREIGN KEY (semester_id) REFERENCES semester (semester_id),
  FOREIGN KEY (student_id)  REFERENCES student  (student_id),
  UNIQUE INDEX (semester_id, student_id)
);

-- similarly ...
CREATE TABLE class(class_id ..., semester_id ..., subject_id ..., class_number ...);
到目前为止,一切都很棒。但是,我们还需要将它们连接起来:

CREATE TABLE grades (
  student_in_class_id INTEGER PRIMARY KEY,
  enrollment_id INTEGER NOT NULL,
  class_id INTEGER NOT NULL,
  grade char(1),
  FOREIGN KEY enrollment (enrollment_id),
  FOREIGN KEY class (class_id),
  UNIQUE INDEX (enrollment_id, class_id)
);
问题:我们究竟应该如何强制要求入学和上课都是同一学期?(简短回答:我们不能

复合键也是如此——在这里,我不需要额外的键来强制外键的唯一组合,默认情况下,主键为我这样做:

CREATE TABLE enrollment (
  semester_id INTEGER NOT NULL,
  student_id INTEGER NOT NULL,
  room_number INTEGER,
  PRIMARY KEY (semester_id, student_id),
  FOREIGN KEY (semester_id) REFERENCES semester (semester_id),
  FOREIGN KEY (student_id)  REFERENCES student  (student_id)
);

-- along the same lines...
class(semester_id ..., subject_id ..., class_number ...)
然后是不祥等级表:

CREATE TABLE grades (
  semester_id INTEGER NOT NULL,
  student_id INTEGER NOT NULL,
  subject_id INTEGER NOT NULL,
  PRIMARY KEY (semester_id, student_id, subject_id),
  FOREIGN KEY (semester_id, student_id) REFERENCES enrollment(semester_id, student_id),
  FOREIGN KEY (semester_id, subject_id) REFERENCES class(semester_id, subject_id)
);
这样,我就可以恰当地表达和约束我的关系

额外奖励:我可以通过简单的连接(而不是通过多个级别遍历模式)获得我的
学期名
学生名
科目名
值。很可能你的级别比这个最简单的示例要多,然后,它将更加明显,它是多么容易回到任何家长关系

更改模式并不复杂,但即使如此:数据建模不是关于数据建模吗?我们能仅仅因为崇拜代理键就抛弃引用完整性吗


注意:Hibernate确实处理复合键。DataMapper for Ruby也是如此。

有人反对这一点:“性能会降低”。我同意所有其他的观点(更难编程,ORMs和框架无法处理复合fk,等等)