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

如何定义一个字段,例如使用JPA注释将email定义为索引。 我们在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

据我所知,没有一个跨JPA-Provider的方式来指定索引。 但是,您始终可以直接在数据库中手动创建它们,大多数数据库将在查询计划期间自动选取它们。

有了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{ 

JPA 2.1(最后)增加了对索引和外键的支持! 详情请看这个博客 。 JPA 2.1是Java EE 7的一部分,已经出来了。

如果你喜欢生活在边缘,你可以从他们的Maven仓库 (groupId:org.eclipse.persistence,artifactId:eclipselink,版本:2.5.0-SNAPSHOT)获取eclipselink的最新快照。 对于只有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.1,因为2.5.0版本的问题(modelgen的东西不工作)。

索引注释的独特手工收集

=规格=

  • JPA 2.1+: javax.persistence.Index (或参见JSR-000338 ,第450页,第11.1.23条)
    JPA @Index注释只能作为@Index等其他注释的一部分使用:

     @Table(indexes = { @Index(...) }) 
  • JDO 2.1+: javax.jdo.annotations.Index

= ORM框架=

  • ♥ Hibernate ORM : org.hibernate.annotations.Index ;
  • OpenJPA : org.apache.openjpa.persistence.jdbc.Index ;
  • EclipseLink : org.eclipse.persistence.annotations.Index ;
  • DataNucleus : org.datanucleus.api.jpa.annotations.Index ;
  • Carbonado (GitHub) : com.amazon.carbonado.Index ;
  • EBean : com.avaje.ebean.annotation.Index ;
  • Ujorm :注释org.ujorm.orm.annot.ColumnindexuniqueIndex属性;
  • 重新查询(GitHub) :注释io.requery.Index ;
  • 暴露 ( Kotlin SQL库): org.jetbrains.exposed.sql.Index , org.jetbrains.exposed.sql.Table#index() 。 例:

     object Persons : IdTable() { val code = varchar("code", 50).index() } 

= Android的 ORM =

  • ♥ ActiveAndroid :Annotation com.activeandroid.annotation.Column具有indexindexGroupsuniqueuniqueGroups属性;
  • ORMLite :Annotation com.j256.ormlite.field.DatabaseField有一个index属性;
  • greenDAO : de.greenrobot.daogenerator.Index ;
  • org.orman.mapper.annotation.Index (GitHub) : org.orman.mapper.annotation.Index ;
  • ★DBFlow (GitHub) : com.raizlabs.android.dbflow.sql.index.Index (使用示例 );
  • 其他 。

=其他(难以分类)=

  • Realm – iOS / Android的备用数据库:注释io.realm.annotations.Index ;
  • Empire-db – 基于JDBC的轻量级但强大的关系数据库抽象层。 它没有通过注释来定义模式。
  • Kotlin NoSQL (GitHub) – 用于处理NoSQL数据库(PoC)的反应式和类型安全DSL:

只要去其中一个。

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

所以你将不得不依赖于提供商的具体扩展。 Hibernate,OpenJPA和EclipseLink显然提供了这样的扩展。 我无法确认DataNucleus,但由于索引定义是JDO的一部分,我猜是这样。

我真的希望索引支持将在下一个版本的规范中得到标准化,从而以某种方式不同意其他答案,我没有看到任何理由不在JPA中包含这样的东西(特别是因为数据库并不总是在你的控制之下)以获得最佳的DDL生成支持。

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

在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中指定

OpenJPA允许你指定非标准的注解来定义属性的索引。

细节在这里 。

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 // F_NAME column indexed @Column(name="L_NAME") private String lastName; ... } 

总结其他答案:

  • Hibernate: org.hibernate.annotations.Index
  • OpenJPA: org.apache.openjpa.persistence.jdbc.Index
  • EclipseLink: org.eclipse.persistence.annotations.Index

我只要去其中一个。 无论如何,它将与JPA 2.1一起来,并且在真的要切换您的JPA提供程序的情况下不应该太难改变。

使用JPA批注不可能这样做。 这是有道理的:在UniqueConstraint明确定义业务规则的地方,索引只是一种加快搜索速度的方法。 所以这应该由DBA来完成。

这个解决方案适用于EclipseLink 2.5,它可以工作(测试):

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

这假设顺序。

Interesting Posts