我想知道使用 Hibernate 进行数据库设计的最佳实践。
我有一个用户实体,它将有很多不同的设置。对于每组设置,我必须将它们添加为用户表中的额外列,或者创建一个单独的实体并将它们与@OneToOne 关系连接起来。据我了解,@OneToMany 和@ManyToOne 关系通常应该出现在单独的表中,因为您不应该有可选的列。
但是@OneToOne 关系还不清楚。我认为有使用@OneToOne 的情况,因为默认情况下 ORM 将选择所有单个属性,并且有很多列会减慢该过程。
我正在谈论的一个例子可以用
来说明@Entity
public class User{
@OneToOne
private ForumSettings forumSettings;
@OneToOne
private AccountSettings accountSettings;
@OneToOne
private SecuritySettings securitySettings;
}
对比
@Entity
public class User{
@Column
private boolean showNSFWContent; //Forum Setting
@Column
private int numberOfCommentsPerPage; //Forum Setting
@Column
private boolean subscribedToNewsLetter; //Account Setting
@Column
private boolean isAccountBanned; //Account Setting
@Column
private boolean isTwoFactorAuthenticationEnabled; //Security Setting
@Column
private boolean alertForSuspiciousLogin; //Security Setting
}
上面是一个简单的例子来展示这个概念,但实际上第二部分会有更多的列。
我知道这可能是基于意见,但我希望有人可以分享这两种选择的优缺点。
非常感谢
最佳答案
您的问题一般是关于数据规范化的。规范化本身是一个广泛的研究领域,基本上是一种构建数据库表以避免冗余并确保更新不会引入异常的方法。
规范化的第一条规则是表格不应包含重复组。在你的情况下是这样。
解决方案 1:将 UserSettings 存储为实体作为映射为一对多关系
@Entity
public class User
@OneToMany
private List<UserSettings> userSettings;
然后您可以通过加入 User
和 UserSettings
实体来查询特定的 setting
类型。
例如(JPQL)
SELECT user u
JOIN u.settings us
WHERE us.settings_type = 'account_settings'
and us.settings_value = 'secure' // or any other logic
这种方法的优点是 UserSettings
将拥有它自己的持久性标识,并且可以由它自己查询。它不依赖于 parent 。
例如:
SELECT q from Query q where ...
解决方案 2:将设置存储在一组基本元素中
您可以在集合中存储用户设置(每个用户都有自己的一组设置)
@Entity
public class User {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
private String name;
...
@ElementCollection
@CollectionTable(name="USER_SETTINGS")
@MapKeyColumn(name="SETTINGS_TYPE")
@Column(name="SETTINGS_VALUE")
Map<String, Boolean> userSettings = new HashMap<>();
UserSettings
集合将存储在一个单独的表中,外键
到 User
表。 UserSettings
没有自己的持久性 ID,依赖于 User
实体,只能通过它的父级('User')查询
解决方案 3:将用户设置存储为嵌入式类型
嵌入类型不是一个实体,它没有自己的持久性 ID 并且取决于父类型,作为父记录的一部分存储在数据库中(在 User
表中)
@Entity
public class User {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
private String name;
...
@Embedded
private UserSettings userSettings;
UserSettings 在单独的类中,但存储在 User
表中。
@Embeddable
public class UserSettings {
private List<String> securitySettings; // or any other collection type
private List<Boolean> forumSettings;
关于java - JPA/Hibernate 中的单独表与额外列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45383087/