使用JPA指定索引(非唯一键)


98

如何定义一个字段,例如email使用JPA批注进行索引。我们需要一个非唯一的键,email因为每天在该字段上有数百万个查询,而没有键的话,它有点慢。

@Entity
@Table(name="person", 
       uniqueConstraints=@UniqueConstraint(columnNames={"code", "uid"}))
public class Person {
    // Unique on code and uid
    public String code;
    public String uid;

    public String username;
    public String name;
    public String email;
}

我已经看到了特定于休眠的注释,但是由于我们仍在决定休眠和数据核之间的关系,因此我试图避免使用特定于供应商的解决方案。

更新:

从JPA 2.1开始,您可以执行此操作。请参阅:此位置不允许使用注释@Index


6
如果您能更新答案,我会很棒,以便人们发现使用JPA 2.1确实可以做到这一点
borjab 2015年

2
您为什么不接受最受好评的答案?
naXa

Answers:


206

使用JPA 2.1,您应该能够做到。

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Index;
import javax.persistence.Table;

@Entity
@Table(name = "region",
       indexes = {@Index(name = "my_index_name",  columnList="iso_code", unique = true),
                  @Index(name = "my_index_name2", columnList="name",     unique = false)})
public class Region{

    @Column(name = "iso_code", nullable = false)
    private String isoCode;

    @Column(name = "name", nullable = false)
    private String name;

} 

更新:如果您需要使用两列或更多列创建和索引,则可以使用逗号。例如:

@Entity
@Table(name    = "company__activity", 
       indexes = {@Index(name = "i_company_activity", columnList = "activity_id,company_id")})
public class CompanyActivity{

感谢Alvin的回答。(+1票)。但是我不得不寻找一些东西,希望这个例子可以使您的生活更轻松
borjab 2014年

正是我在寻找什么-删除了一个简单干净的代码-不仅描述了整个过程。谢谢+1。
DominikAngerer 2014年

2
@borjab-您能否给我一个提示,在哪里可以找到在@Index注释中使用注释的“官方”示例或规范@Table?我在JSR 338上进行了搜索,但没有在那找到它。您的帖子对我非常有用。
JimHawkins '16

2
@Ulrich并不完全是官方文档,而是oracle博客blogs.oracle.com/arungupta/entry/jpa_2_1_schema_g​​eneration
borjab 2016年

我想知道,如果我有一个带有@Column(unique = true)的列,它是否会合并到索引列表中(因为唯一也是一个索引)?
wkrueger

34

精选的独特的索引注释集合

=规格=

= ORM框架=

= Android版 ORM =

=其他(难以分类)=

  • 领域 -适用于iOS / Android的备用数据库:注释io.realm.annotations.Index
  • 帝国数据库基于JDBC的轻量级但功能强大的关系数据库抽象层。它没有通过注释定义架构;
  • Kotlin NoSQL (GitHub) -用于处理NoSQL数据库(PoC)的反应式和类型安全DSL:
  • Slick-用于Scala的反应性功能关系映射。它没有通过注释进行模式定义。

只是去其中之一。


31

JPA 2.1(最终)添加了对索引和外键的支持!有关详细信息,请参见此博客。JPA 2.1是Java EE 7的一部分。

如果您喜欢生活在边缘,可以从其maven存储库中获取eclipselink的最新快照。(groupId:org.eclipse.persistence,artifactId:eclipselink,版本:2.5.0-SNAPSHOT)。对于仅JPA注释(一旦支持2.1,任何提供程序都可以使用),请使用artifactID:javax.persistence,版本:2.1.0-SNAPSHOT。

我将它用于直到发行后才能完成的项目,而且我还没有注意到任何可怕的问题(尽管我并没有对它做任何太复杂的事情)。

更新(2013年9月26日):如今(中央)存储库中提供eclipselink的发布和候选版本,因此您不再需要在Maven项目中添加eclipselink存储库。最新发行版本是2.5.0,但也存在2.5.1-RC3。由于2.5.0版本存在问题,我会尽快切换到2.5.1(modelgen的东西不起作用)。


9

在JPA 2.1中,您需要执行以下操作

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.Table;

@Entity(name="TEST_PERSON")
@Table(
    name="TEST_PERSON", 
    indexes = {
       @Index(name = "PERSON_INDX_0", columnList = "age"),
       @Index(name = "PERSON_INDX_1", columnList = "fName"),
       @Index(name = "PERSON_INDX_1", columnList = "sName")  })
public class TestPerson {

    @Column(name = "age", nullable = false)
    private int age;

    @Column(name = "fName", nullable = false)
    private String firstName;

    @Column(name = "sName", nullable = false)
    private String secondName;

    @Id
    private long id;

    public TestPerson() {
    }
}

在上面的示例中,表TEST_PERSON将具有3个索引:

  • 主键ID上的唯一索引

  • 年龄指数

  • FNAME,SNAME上的复合索引

注1:通过使用两个具有相同名称的@Index批注来获得复合索引

注意2:您在columnList中指定列名,而不是fieldName


5

我真的很希望能够以一种标准化的方式指定数据库索引,但是遗憾的是,这不是JPA规范的一部分(也许是因为JPA规范不需要DDL生成支持,这对于这样的功能)。

因此,您必须依靠提供商特定的扩展。Hibernate,OpenJPA和EclipseLink显然提供了这样的扩展。我无法确定DataNucleus,但是由于索引定义是JDO的一部分,所以我想也可以。

我真的希望索引支持在规范的下一版本中得到标准化,因此以某种方式不同意其他答案,我看不出有什么充分的理由不在JPA中包含此类内容(特别是因为数据库并不总是在您的控制之下)获得最佳的DDL生成支持。

顺便说一句,我建议下载JPA 2.0规范。


4

据我所知,还没有跨JPA提供程序的方式来指定索引。但是,您始终可以直接在数据库中手动创建它们,大多数数据库会在查询计划期间自动选择它们。


2
大声笑,那就是假设您拥有DBA来完成DBA的工作(:
Jacob Jacob 2010年

3
我发现有一种方法可以做“唯一”但没有索引的方法,这有点奇怪。
雅各布

7
@Jacob-那么在应用程序级别知道某个字段是否唯一是很重要的。另一方面,索引是为了优化数据库访问。就我所知,在Java层上不需要知道列是否是索引。就像您说的那样,如果似乎特定的列将从中受益,则DBA可以设置索引。
Java Drinker 2010年

1
@Jacob,没有索引支持,因为这只是一种优化(通常是重要的,但仍然是优化)。OTOH(一个字段(或一组字段)是否唯一)取决于模型,并且会影响正确性。此外,不需要成熟的200USD /小时DBA,通常只需一些简单的索引创建语句即可。
塔索斯·巴索科斯


2

EclipseLink提供了一个注释(例如@Index)来定义列上的索引。有一个例子使用。示例的一部分包括在内...

分别为firstName和lastName字段建立索引。

@Entity
@Index(name="EMP_NAME_INDEX", columnNames={"F_NAME","L_NAME"})  // Columns indexed together
public class Employee{
    @Id
    private long id;

    @Index                      // F_NAME column indexed
    @Column(name="F_NAME")
    private String firstName;

    @Index                      // L_NAME column indexed
    @Column(name="L_NAME")
    private String lastName;
    ...
}

1

OpenJPA允许您指定非标准注释以定义属性索引。

详细信息在这里




0

该解决方案适用于EclipseLink 2.5,并且可以正常工作(经过测试):

@Table(indexes = {@Index(columnList="mycol1"), @Index(columnList="mycol2")})
@Entity
public class myclass implements Serializable{
      private String mycol1;
      private String mycol2;
}

这假设升序。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.