我想知道hibernate在数据库设计方面的最佳实践。
我有一个用户实体,它将有很多不同的设置。对于每一组设置,我必须将它们作为额外列添加到用户表中,或者创建一个单独的实体并将它们与@onetoone关系连接起来。我的理解是,@onetomany和@manytoone关系通常应该在单独的表中发生,因为不应该有可选的列。
但对于“一元关系”来说,这还不太清楚。我认为使用@onetoone是有原因的,因为orms默认情况下会选择所有单个属性,并且有很多列会减慢这个过程。
我所说的一个例子可以用
@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:将用户设置作为实体存储为映射作为一个家庭关系
@Entity
public class User
@OneToMany
private List<UserSettings> userSettings;
然后您可以通过连接
setting
和User
实体来查询特定的UserSettings
类型。例如(jpql)
SELECT user u
JOIN u.settings us
WHERE us.settings_type = 'account_settings'
and us.settings_value = 'secure' // or any other logic
这种方法的优点是
UserSettings
将拥有自己的持久性标识,并且可以由自己的持久性标识查询。它不依赖于父母。例如:
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
集合将存储在一个单独的表中,其中包含foreign key
到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/