【发布时间】:2016-12-10 08:12:29
【问题描述】:
让我们假设应该从头开始构建的应用程序的域模型描述如下:
一个人可能住在一个地址。一个人可以拥有多辆汽车。
如果我必须首先设计数据库,我可能会提出以下数据库设计(规范化、级联等不应该对我的具体问题起主要作用)。
Person (id, name)
Address (id, street, zip, city, person_id)
Car (id, manufacturer, yearBuilt, color, person_id)
我主要遵循标准设计概念(例如在此链接中描述http://db.grussell.org/section006.html)。
如您所见,地址表具有人表的外键,因为人-地址关系可以被认为是可选的。
一个人可以拥有多辆汽车的事实是通过将一个外键放在汽车表中的一个人来实现的。我认为这是建模 1..m 关系的标准方法。
如果我必须先设计领域模型,我可能会想出以下设计:
public class Person {
private String name;
private Address address;
private List<Car> cars;
// Getters and setters
}
public class Address {
private String street;
private String zip;
private String city;
// Getters and setters
}
public class Car {
private String color;
private Date yearBuilt;
// Getters and setters
}
在该域模型中,Person 类具有所有必要的关系。 Address 和 Car 类不需要知道他们拥有 Person 的任何信息。
我现在可以通过添加@Entity 并为每个类提供@Id 属性来将这些类转换为JPA 实体。
@Entity
public class Person implements Serializable {
@Id
private Long id;
private String name;
@OneToOne
private Address address;
@OneToMany
private List<Car> cars;
public Person() { }
// Getters and setters
}
@Entity
class Address implements Serializable {
@Id
private Long id;
private String street;
private String zip;
private String city;
public Address() { }
// Getters and setters
}
@Entity
class Car implements Serializable {
@Id
private Long id;
private String color;
private Date yearBuilt;
public Car() { }
// Getters and setters
}
如果我的 JPA 提供者根据提供的注释创建表,则创建以下数据库结构:
Person (id, name, address_id)
Address (id, street, zip, city)
Car (id, manufacturer, yearBuilt, color)
Person_Car (person_id, car_id)
如您所见,如果我必须先设计数据库,这与我将创建的数据库结构不对应。我发现 JPA 提供者创建的数据库模型存在一些缺陷:
- 由于人员-地址关系是可选的,因此我会将 Person 的外键放入 Address 表中,反之亦然。
- 由于建模 1..m 关系的标准方法是将拥有类的外键放入详细信息类中,因此我永远不会提出关系或关联表。如果关系不是由附加属性描述的,我为什么要这样做?
- 要将 Person 连接到 Car,JPA 提供程序需要对关系或关联表执行额外的连接。这会显着降低性能吗?
我现在可以做的是为 JPA 实体类提供额外的字段和/或注释,以争取人们可能期望的数据库结构。
是否需要努力实现能够创建预期数据库结构的域模型/JPA 实体设计(就像使用了数据库优先方法一样)?如果是这样,是否可以接受与直观创建的域模型不同的域模型?设计将创建某种“最佳实践”数据库结构的域模型/JPA 实体模型有哪些优势?
【问题讨论】:
-
你的问题往往过于宽泛,因为其中有很多子问题......
标签: jpa database-design