如何使用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;
}
我已经看到了一个特定于hibernate的注释,但我正在尝试避免供应商特定的解决方案,因为我们仍在决定hibernate和datanucleus。
更新:
从JPA 2.1开始,您可以这样做。请参阅:The annotation @Index is disallowed for this location
答案 0 :(得分:167)
使用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{
答案 1 :(得分:28)
JPA 2.1(最后)增加了对索引和外键的支持!有关详细信息,请参阅this blog。 JPA 2.1是Java EE 7的一部分,它已经发布了。
如果您喜欢生活在边缘,您可以从maven repository(groupId:org.eclipse.persistence,artifactId:eclipselink,version:2.5.0-SNAPSHOT)获取eclipselink的最新快照。对于JPA注释(一旦它们支持2.1,它应该适用于任何提供者)使用artifactID:javax.persistence,version:2.1.0-SNAPSHOT。
我正在将它用于一个项目,直到它发布之后才能完成,我没有注意到任何可怕的问题(虽然我没有做任何太复杂的事情)。
更新(2013年9月26日):现在,中央(主)存储库中提供了eclipselink的候选版本,因此您不必再在Maven项目中添加eclipselink存储库。最新发布的版本是2.5.0,但也存在2.5.1-RC3。由于2.5.0版本的问题,我会尽快切换到2.5.1(modelgen的东西不起作用)。
答案 2 :(得分:28)
JPA 2.1+:javax.persistence.Index
(或参见JSR-000338 PDF,第452页,第11.1.23项)
JPA @Index
注释只能用作@Table
,@SecondaryTable
等其他注释的一部分:
@Table(indexes = { @Index(...) })
org.hibernate.annotations.Index
; org.apache.openjpa.persistence.jdbc.Index
和org.apache.openjpa.persistence.jdbc.ElementIndex
(请参阅Reference Guide); org.eclipse.persistence.annotations.Index
; org.datanucleus.api.jpa.annotations.Index
; com.amazon.carbonado.Index
; org.ujorm.orm.annot.Column
,index
和uniqueIndex
属性; io.requery.Index
; Exposed(Kotlin SQL Library):org.jetbrains.exposed.sql.Index,org.jetbrains.exposed.sql.Table#index()。示例:
object Persons : IdTable() {
val code = varchar("code", 50).index()
}
com.activeandroid.annotation.Column
包含index
,indexGroups
,unique
和uniqueGroups
属性; com.reactiveandroid.annotation.Column
包含index
,indexGroups
,unique
和uniqueGroups
属性; com.j256.ormlite.field.DatabaseField
具有index
属性; org.greenrobot.greendao.annotation.Index
; org.orman.mapper.annotation.Index
; com.raizlabs.android.dbflow.sql.index.Index
(example用法); io.realm.annotations.Index
; 请选择其中一个。
答案 3 :(得分:6)
在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
答案 4 :(得分:5)
我真的希望能够以标准化方式指定数据库索引,但遗憾的是,这不是JPA规范的一部分(可能是因为JPA规范不要求DDL生成支持,这是一种这种特征的路障)。
因此,您必须依赖提供商特定的扩展。 Hibernate,OpenJPA和EclipseLink显然提供了这样的扩展。我无法确认DataNucleus,但由于索引定义是JDO的一部分,我想它确实如此。
我真的希望索引支持在下一版本的规范中得到标准化,因此不同意其他答案,我认为没有任何理由不在JPA中包含这样的东西(特别是因为数据库并不总是在您的控制)以获得最佳的DDL生成支持。
顺便说一句,我建议下载JPA 2.0规范。
答案 5 :(得分:3)
据我所知,没有跨JPA-Provider方法来指定索引。但是,您始终可以直接在数据库中手动创建它们,大多数数据库将在查询规划期间自动选择它们。
答案 6 :(得分:2)
EclipseLink提供了一个注释(例如@Index)来定义列的索引。其使用example。部分示例包括......
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;
...
}
答案 7 :(得分:1)
OpenJPA允许您指定非标准注释以定义属性上的索引。
详情为here。
答案 8 :(得分:1)
总结其他答案:
org.hibernate.annotations.Index
org.apache.openjpa.persistence.jdbc.Index
org.eclipse.persistence.annotations.Index
我会选择其中一个。无论如何它都会附带JPA 2.1,如果您真的想要切换JPA提供程序,不应该太难改变。
答案 9 :(得分:0)
使用JPA注释无法做到这一点。这是有道理的:在UniqueConstraint明确定义业务规则的地方,索引只是一种使搜索更快的方法。所以这应该由DBA完成。
答案 10 :(得分:0)
此解决方案适用于EclipseLink 2.5,它可以工作(测试):
@Table(indexes = {@Index(columnList="mycol1"), @Index(columnList="mycol2")})
@Entity
public class myclass implements Serializable{
private String mycol1;
private String mycol2;
}
这假设上升顺序。