我有3个模型Person
,Role
和Position
代表像这样的足球俱乐部中的人
public class Person {
private Long id;
private String name;
private Role role;
}
public class Role {
private Long id;
private String name; //like manager, goalkeeping_coach, player
}
public class Position {
private Long id;
private String name; //striker, midfielder, defender, goalkeeper
}
问题在于,position
仅对于一个人来说player
才有意义。所以如果我这样做
public class Person {
private Long id;
private String name;
private Role role;
private Position position;
}
然后,对于所有不具有person
角色的player
实例,position
字段将存储空值。同样,可能还有其他属性仅对manager
和/或goalkeeping_coach
实例有意义。
我尝试使Person
类抽象化
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Person {
private Long id;
private String name;
private Role role;
}
public class Player extends Person {
private Position position;
}
public class Manager extends Person {
}
这将导致player
和manager
实例保存在不同的表中。但是,如果role
中的person
发生变化(例如球员退役并成为俱乐部的经理),就会出现问题。然后,我不得不将行从一个表移动到另一个表(例如,删除player
实例,并使用除manager
数据之外的相同数据来创建新的position
实例),似乎不是一个好方法。
那么处理这种情况的最佳方法是什么?是否可以像第一种情况一样具有空值?
答案 0 :(得分:2)
要求是Person
和Role
之间的连接可以更改。
该模型可以反映出,如果为该连接以及Person
和Position
// Person table has only Person details
public class Person {
private Long id;
private String name;
}
// Role table has only Role details
public class Role {
private Long id;
private String name; //like manager, goalkeeping_coach, player
}
// Position table has only ...
public class Position {
private Long id;
private String name; //striker, midfielder, defender, goalkeeper
}
// connection of Person and Role
public class PersonRole {
private Long person_id;
private Long role_id;
}
// connection of Person and Position
public class PersonPosition {
private Long person_id;
private Long position_id;
}
此设计解决了人员更换角色的要求以及职位的条件相关性。它还可以满足未来的需求,例如具有多个角色和职位的人
编辑: 我发现我所描述的实际上是数据库模型。在Java中,您可以将连接表建模为多对多关系(如果使用某些ORM)
答案 1 :(得分:1)
这里的第一个本质区别是我们在说Java辅助代码还是数据库辅助代码。
对于Java表示: 从Person派生Player和Manager似乎是正确的。那里没有空字段。该行为将考虑是玩家还是经理,并且您可以编写使玩家成为经理的转移构造函数(反之亦然,如果有意义)
对于数据库表示:
可以使用空字段(就空间而言,它们很便宜,您可以通过使用空检查来查询它们)。是否要将它们映射到自己的表中取决于您要分别查询还是组合查询。有时您希望查询Person
而不是仅查询Player
,例如,以估算总工资。然后,您必须union
(假设您使用某种形式的SQL数据库)。
因此,从根本上来说,正确的答案是,没有一个正确的答案,这取决于您的整个体系结构和软件的用途,但是无论何时何地,您都必须在关键位置做出任何调整。数据库交互。
答案 2 :(得分:0)
解决此问题的一种方法是使同一个表同时服务于人员和经理以及实际上任何其他类型的人员。 您将拥有未使用的行,具体取决于人员类型,但所有公共字段将保留在该单一表中。这样,当角色更改时,无需删除行并在另一个表上创建它们。 您必须为人员类型添加一个字段。
答案 3 :(得分:0)
您遇到了一个常见问题。尽管经理满足“是人”标准,但这可能仅适用于特定时间段,并且数据库记录通常适用于更长的时间段。
对此建模的正确方法是拥有Person和Role表(您已经拥有),以及一个PersonRole链接表,该表将具有personId,roleId,startDate和endDate字段。这样可以解决数据建模问题,但会使您的代码复杂化。
但是,许多应用程序只关注时间(例如下一个游戏日期,下一个发薪日)。这些可以使用您建议的“经理扩展人员”层次结构,因为它在某个实例上及时成立。