JPAを使用したインデックス(一意でないキー)の指定


98

たとえばemail、JPAアノテーションを使用してインデックスを持つなど、フィールドをどのように定義しますか。email文字通り何百万ものクエリが1日あたりこのフィールドにあり、キーがないと少し遅いので、一意でないキーをオンにする必要があります。

@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以降では、これを行うことができます。参照:この場所ではアノテーション@Indexは許可されていません


6
人々はJPA 2.1でそれを行うための方法が本当にあることを見つけるように、あなたは答えを更新することができれば、私は素晴らしいことだ
borjab

2
最も賛成された回答を受け入れませんか?
naXa

回答:


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;

} 

更新:2つ以上の列を作成してインデックスを作成する必要がある場合は、コンマを使用できます。例えば:

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

答えてくれたアルビンに感謝します。(+1票)。しかし、私はいくつかのことを探す必要がありました。この例があなたの人生を楽にしてくれることを願っています
ボルジャブ2014年

正確に私が探していたもの-単純でクリーンなコードをスニップ-すべてを説明するだけではありません。ありがとう+1。
DominikAngerer 2014年

2
@borjab- @Index注釈内で@Table注釈を使用するための「公式」の例または仕様を見つけることができるヒントを教えていただけますか?JSR 338で検索しましたが、見つかりませんでした。あなたの投稿は私にとって非常に役に立ちます。
JimHawkins

2
@Ulrich公式のドキュメントではなく、オラクルのブログblogs.oracle.com/arungupta/entry/jpa_2_1_schema_g​​eneration
ボルジャブ

@Column(unique = true)の列がある場合、(uniqueはインデックスでもあるため)インデックスリストにマージされますか?
wkrueger

34

厳選されたユニークなインデックスアノテーションのコレクション

=仕様=

= ORMフレームワーク=

= Android向け ORM =

=その他(分類が難しい)=

  • レルム-iOS / Android用の代替DB:注釈io.realm.annotations.Index ;
  • エンパイアdb -JDBCに基づく軽量で強力なリレーショナルDB抽象化レイヤー。アノテーションによるスキーマ定義はありません。
  • Kotlin NoSQL (GitHub) -NoSQLデータベース(PoC)を操作するためのリアクティブでタイプセーフなDSL:???
  • Slick -Scala向けのリアクティブ関数リレーショナルマッピング。アノテーションによるスキーマ定義はありません。

そのうちの1つに行くだけです。


31

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、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は動作しません)。


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の一意のインデックス

  • AGEのインデックス

  • FNAME、SNAMEの複合インデックス

注1:同じ名前の@Indexアノテーションを2つ持つことにより、複合インデックスを取得します。

注2:columnNameは、fieldNameではなくcolumnListで指定します。


5

データベースインデックスを標準化された方法で指定できるようにしたいのですが、残念ながら、これはJPA仕様の一部ではありません(JPA仕様ではDDL生成サポートが必要ないため、このような機能)。

したがって、そのためにはプロバイダー固有の拡張機能に依存する必要があります。Hibernate、OpenJPA、EclipseLinkは明らかにそのような拡張機能を提供しています。DataNucleusについては確認できませんが、インデックスの定義はJDOの一部であるため、そうだと思います。

インデックスのサポートが仕様の次のバージョンで標準化され、他の回答とどうにか一致しないことを本当に望みます。JPAにそのようなものを含めないことには、特に理由はありません(特にデータベースが常に制御できるわけではないためです)。最適なDDL生成サポート。

ところで、JPA 2.0仕様をダウンロードすることをお勧めします。


4

私の知る限りでは、JPAプロバイダーを超えてインデックスを指定する方法はありません。ただし、いつでもデータベースに直接手動で作成できます。ほとんどのデータベースでは、クエリの計画時に自動的に取得されます。


2
笑、それはあなたがDBAの仕事をするDBAを持っていると仮定している(:
Jacob

3
インデックスを作成する方法ではなく、「一意」を実行する方法があるのは少し奇妙です。
Jacob

7
@Jacob-一部のフィールドが一意になるかどうかをアプリケーションレベルで知ることが重要です。一方、インデックスは、dbアクセスを最適化するためのものです。Javaレイヤーで列がインデックスであるかどうかを(私が知る限り)知る必要はありません。あなたが言ったように、特定の列がそれから利益を得ると思われる場合、DBAはインデックスを設定できます。
Java Drinker 2010

1
@Jacob、それは単なる最適化であるため、インデックスのサポートはありません(通常、重要なものですが、依然として最適化です)。フィールド(またはフィールドのセット)が一意であるか、モデルに依存しない場合のOTOHは、正確さに影響します。また、本格的な200USD / Hr DBAの必要もないため、通常はいくつかの簡単なインデックス作成ステートメントで十分です。
Tassos Bassoukos、2010


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

JPAアノテーションを使用してそれを行うことはできません。これは理にかなっています。UniqueConstraintがビジネスルールを明確に定義している場合、インデックスは検索を高速化するための手段にすぎません。したがって、これは実際にはDBAが行う必要があります。


0

このソリューションはEclipseLink 2.5用であり、機能します(テスト済み)。

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

これは、昇順を前提としています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.