休眠中索引和@NaturalId之间的区别

Posted

技术标签:

【中文标题】休眠中索引和@NaturalId之间的区别【英文标题】:Difference between indexing and @NaturalId in hibernate 【发布时间】:2017-07-29 23:25:55 【问题描述】:

有一些关于自然标识符的文章,我在那里读到自然标识符促进了对休眠中最常用字段的查找。 In this post,他们描述了自然标识符对于使用特定字段查找任何数据要好得多。他们还描述了自然标识符由 hibernate 索引,hibernate 通过使用该索引来提高查找性能。

据我所知,还有一些方法可以为特定字段创建索引,使用这种方式可以获得查找性能。那么使用自然标识符比一般索引有什么优势呢?

例如,我可以创建一个具有适当索引的实体类,例如,

@Entity
@Table(name = "users", indexes = 
    @Index(columnList = "username", name = "users_username")
)
public class User implements Serializable 

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "username", unique = true)
    private String username;

    @Column(name = "email_id")
    private String email;

    ------------


其他方式我可以创建一个没有索引但具有自然标识符的实体,例如,

@Entity
@Table(name = "users")
public class User implements Serializable 

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @NaturalId
    @Column(name = "username", unique = true)
    private String username;

    @Column(name = "email_id")
    private String email;

    ------------


根据定义,两者都以相同的方式工作,并且都在后台使用索引方法。那么从技术上讲,索引和自然标识符之间有什么区别?推荐哪种方法以及它比另一种更好?

【问题讨论】:

【参考方案1】:

当您使用@NaturalId 时,Hibernate 将维护自然 id 到主键的映射。例如,如果您有如下的 User 实体:

//This is pseudo-code

User 
@Id
long id;

@NaturalId
String username;

Hibernate 将存储哪些用户名映射到哪些 id,这意味着如果一个实体已经与会话对象关联,Hibernate 可以通过自然 id 从会话中加载它。 (此功能也可以扩展到二级缓存)。

索引将创建一个附加列,以使原始索引列的所有行保持排序顺序。可以对索引列进行二分查找,以减少查找时检查的行数。

我相信唯一约束会自动索引 Postgres 中的相应列。我个人同时使用唯一约束和自然 id 注释。

【讨论】:

非常感谢。正如你所说,自然标识符比索引有一些额外的好处,而索引比自然标识符有一些额外的重载。那么,你想推荐什么?我应该使用自然标识符并使​​用索引离开吗? 两者并不相互排斥。在加载对象时,Hibernate 在内部使用 NaturalId。 Index 注释在模式创建期间使用。如果您的模式是由 Hibernate 生成的,那么当 Hibernate 看到 Index 注释时,它将为该列(在数据库中)创建一个索引。对于经常查询的唯一字段,我建议使用@naturalid 和@column(name="...", unique=true)

以上是关于休眠中索引和@NaturalId之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

EclipseLink 相当于 Hibernate 的 NaturalID 概念

会话与会话工厂之间的差异 - 休眠?

聚集索引和非聚集索引之间的区别 [重复]

休眠搜索以处理两个不同实体对象的相同索引

电脑的休眠和睡眠有啥区别

MongoDB - 文本字段索引和文本索引之间的区别?