Menentukan Indeks (Kunci Non-Unik) Menggunakan JPA

100

Bagaimana Anda mendefinisikan bidang, misalnya emailmemiliki indeks menggunakan penjelasan JPA. Kami memerlukan kunci non-unik emailkarena ada jutaan kueri di bidang ini per hari, dan agak lambat tanpa kuncinya.

@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;
}

Saya telah melihat anotasi khusus hibernasi tetapi saya mencoba menghindari solusi khusus vendor karena kami masih memutuskan antara hibernasi dan datanukleus.

MEMPERBARUI:

Mulai JPA 2.1, Anda dapat melakukan ini. Lihat: Anotasi @Index tidak diizinkan untuk lokasi ini

Yakub
sumber
6
Saya akan sangat baik jika Anda dapat memperbarui jawabannya sehingga orang-orang menemukan bahwa dengan JPA 2.1 ada cara untuk melakukannya
borjab
2
Mengapa Anda tidak menerima jawaban yang paling disukai?
naXa

Jawaban:

208

Dengan JPA 2.1 Anda seharusnya bisa melakukannya.

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;

} 

Pembaruan : Jika Anda perlu membuat dan mengindeks dengan dua atau lebih kolom, Anda dapat menggunakan koma. Sebagai contoh:

@Entity
@Table(name    = "company__activity", 
       indexes = {@Index(name = "i_company_activity", columnList = "activity_id,company_id")})
public class CompanyActivity{
borjab.dll
sumber
Terima kasih kepada Alvin atas jawabannya. (+1 suara). Tetapi saya harus mencari beberapa hal yang saya harap contoh ini dapat membuat hidup Anda lebih mudah
borjab
Persis apa yang saya cari - kode sederhana dan bersih terpotong - tidak hanya menjelaskan semuanya. Terima kasih +1.
DominikAngerer
2
@borjab - dapatkah Anda memberi saya petunjuk di mana saya dapat menemukan contoh atau spesifikasi "resmi" untuk menggunakan @Indexanotasi dalam @Tableanotasi? Saya telah mencari di JSR 338 tetapi saya tidak menemukannya di sana. Posting Anda sangat berguna bagi saya.
JimHawkins
2
@Ulrich Bukan dokumentasi resmi tetapi blog oracle blogs.oracle.com/arungupta/entry/jpa_2_1_schema_generation
borjab
Saya bertanya-tanya, jika saya memiliki kolom dengan @Column (unique = true), apakah itu digabungkan ke daftar indeks (karena unique juga merupakan indeks)?
wkrueger
34

Koleksi unik anotasi Indeks pilihan tangan

= Spesifikasi =

= ORM Frameworks =

= ORM untuk Android =

= Lainnya (sulit dikategorikan) =

  • Realm - DB Alternatif untuk iOS / Android: Annotation io.realm.annotations.Index;
  • Empire-db - lapisan abstraksi DB relasional yang ringan namun kuat berdasarkan JDBC. Ini tidak memiliki definisi skema melalui penjelasan;
  • Kotlin NoSQL (GitHub) - DSL reaktif dan aman jenis untuk bekerja dengan database NoSQL (PoC): ???
  • Slick - Pemetaan Relasional Fungsional Reaktif untuk Scala. Ini tidak memiliki definisi skema melalui anotasi.

Pergi saja untuk salah satunya.

naXa
sumber
31

JPA 2.1 (akhirnya) menambahkan dukungan untuk indeks dan kunci asing! Lihat blog ini untuk detailnya. JPA 2.1 adalah bagian dari Java EE 7 yang sudah keluar.

Jika Anda suka hidup di edge, Anda bisa mendapatkan snapshot terbaru untuk eclipselink dari repositori maven mereka (groupId: org.eclipse.persistence, artifactId: eclipselink, versi: 2.5.0-SNAPSHOT). Untuk anotasi JPA saja (yang seharusnya berfungsi dengan penyedia apa pun setelah mendukung 2.1) gunakan artifactID: javax.persistence, versi: 2.1.0-SNAPSHOT.

Saya menggunakannya untuk proyek yang tidak akan selesai sampai setelah rilis, dan saya belum melihat adanya masalah yang mengerikan (walaupun saya tidak melakukan sesuatu yang terlalu rumit dengannya).

UPDATE (26 Sep 2013): Saat ini versi kandidat rilis dan rilis eclipselink tersedia di repositori pusat (utama), jadi Anda tidak perlu lagi menambahkan repositori eclipselink di project Maven. Versi rilis terbaru adalah 2.5.0 tetapi 2.5.1-RC3 juga hadir. Saya akan beralih ke 2.5.1 ASAP karena masalah dengan rilis 2.5.0 (barang modelgen tidak berfungsi).

Alvin Thompson
sumber
9

Di JPA 2.1 Anda perlu melakukan hal berikut

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() {
    }
}

Dalam contoh di atas, tabel TEST_PERSON akan memiliki 3 indeks:

  • indeks unik pada ID kunci utama

  • indeks pada AGE

  • indeks gabungan di FNAME, SNAME

Catatan 1: Anda mendapatkan indeks majemuk dengan memiliki dua anotasi @Index dengan nama yang sama

Catatan 2: Anda menentukan nama kolom di columnList bukan fieldName

James Clayton
sumber
5

Saya benar-benar ingin dapat menentukan indeks basis data dengan cara standar tetapi, sayangnya, ini bukan bagian dari spesifikasi JPA (mungkin karena dukungan pembuatan DDL tidak diperlukan oleh spesifikasi JPA, yang merupakan semacam penghalang untuk fitur seperti itu).

Jadi, Anda harus bergantung pada ekstensi khusus penyedia untuk itu. Hibernate, OpenJPA dan EclipseLink jelas menawarkan ekstensi seperti itu. Saya tidak dapat mengonfirmasi untuk DataNucleus tetapi karena definisi indeks adalah bagian dari JDO, saya rasa memang demikian.

Saya sangat berharap dukungan indeks akan distandarisasi dalam versi spesifikasi berikutnya dan dengan demikian entah bagaimana tidak setuju dengan jawaban lain, saya tidak melihat alasan yang baik untuk tidak memasukkan hal seperti itu di JPA (terutama karena database tidak selalu di bawah kendali Anda) untuk dukungan generasi DDL yang optimal.

Omong-omong, saya sarankan mengunduh spesifikasi JPA 2.0.

Pascal Thivent
sumber
4

Sejauh yang saya tahu, tidak ada cara lintas-Penyedia-JPA untuk menentukan indeks. Namun, Anda selalu dapat membuatnya dengan tangan langsung di database, sebagian besar database akan mengambilnya secara otomatis selama perencanaan kueri.

Tassos Bassoukos
sumber
2
lol, itu dengan asumsi Anda memiliki DBA yang melakukan pekerjaan DBA (:
Jacob
3
Saya merasa agak aneh bahwa ada cara untuk melakukan "unik" tetapi tidak ada cara untuk melakukan indeks.
Yakub
7
@Jacob - Baik, penting untuk mengetahui di tingkat aplikasi apakah beberapa bidang akan unik atau tidak. Indeks, di sisi lain, ditujukan untuk mengoptimalkan akses db. Tidak perlu (sejauh yang saya lihat) untuk mengetahui apakah kolom merupakan indeks atau tidak pada lapisan java. Seperti yang Anda katakan, DBA dapat menyiapkan indeks jika tampaknya kolom tertentu akan mendapat manfaat darinya.
Java Drinker
1
@Jacob, tidak ada Index suport karena itu hanyalah optimasi (biasanya yang penting, tapi tetap optimasi). OTOH jika suatu bidang (atau kumpulan bidang) unik atau tidak bergantung pada model, dan akan mempengaruhi kebenaran. Selain itu, tidak perlu DBA 200USD / Hr yang lengkap, beberapa pernyataan pembuatan indeks sederhana biasanya sudah cukup.
Tassos Bassoukos
8
JPA 2.1 Menentukanjavax.persistence.Index
Lukas Eder
2

EclipseLink menyediakan anotasi (mis. @Index ) untuk menentukan indeks pada kolom. Ada contohnya penggunaannya. Bagian dari contoh disertakan ...

Bidang firstName dan lastName diindeks, bersama-sama dan satu per satu.

@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;
    ...
}
Nathan
sumber
1

OpenJPA memungkinkan Anda menentukan anotasi non-standar untuk menentukan indeks pada properti.

Detailnya ada di sini .

ahli
sumber
0

Tidak mungkin melakukannya menggunakan anotasi JPA. Dan ini masuk akal: jika UniqueConstraint secara jelas mendefinisikan aturan bisnis, indeks hanyalah cara untuk mempercepat penelusuran. Jadi ini benar-benar harus dilakukan oleh DBA.

Thierry-Dimitri Roy
sumber
0

Solusi ini untuk EclipseLink 2.5, dan berfungsi (diuji):

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

Ini mengasumsikan tatanan ascendant.

Joe Almore
sumber