指定索引(非唯一键)使用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.Column
,index
和uniqueIndex
属性; - 重新查询(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
具有index
,indexGroups
,unique
和uniqueGroups
属性; - 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; }
这假设顺序。