JPA Kullanarak Bir Dizin (Benzersiz Olmayan Anahtar) Belirtme


102

Bir alanı nasıl tanımlarsınız, örneğin emailJPA açıklamalarını kullanan bir dizine sahip olarak. Üzerinde benzersiz olmayan bir anahtara ihtiyacımız emailvar çünkü bu alanda her gün kelimenin tam anlamıyla milyonlarca sorgu var ve anahtarsız biraz yavaş.

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

Hazırda bekletme moduna özgü bir ek açıklama gördüm, ancak hala hazırda bekletme ve datanucleus arasında karar verdiğimiz için satıcıya özgü çözümlerden kaçınmaya çalışıyorum.

GÜNCELLEME:

JPA 2.1'den itibaren bunu yapabilirsiniz. Bakınız: @Index ek açıklamasına bu konum için izin verilmiyor


6
Cevabı güncellerseniz harika olurum, böylece insanlar JPA 2.1 ile bunu yapmanın gerçekten bir yolu olduğunu
anlarlar

2
Neden en çok oy alan cevabı kabul etmiyorsun?
naXa

Yanıtlar:


215

JPA 2.1 ile bunu yapabilmelisiniz.

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;

} 

Güncelleme : İki veya daha fazla sütun oluşturmanız ve dizine eklemeniz gerekirse, virgül kullanabilirsiniz. Örneğin:

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

Cevabı için Alvin'e teşekkürler. (+1 oy). Ama birkaç şey
aramam gerekiyordu

Tam olarak aradığım şey - kesilmiş basit ve temiz bir kod - sadece her şeyi açıklamakla kalmıyor. Teşekkürler +1.
DominikAngerer

2
@borjab - @Indexek açıklamada ek açıklamayı kullanmak için "resmi" bir örnek veya spesifikasyonu nerede bulabileceğim konusunda bana bir ipucu verebilir misiniz @Table? JSR 338'de aradım ama orada bulamadım. Gönderiniz benim için çok faydalı.
JimHawkins

2
@Ulrich Tam olarak resmi belge değil, oracle blog blogs.oracle.com/arungupta/entry/jpa_2_1_schema_generation
borjab

Merak ediyorum, @Column (unique = true) olan bir sütunum varsa, indeksler listesine birleştiriliyor mu (çünkü unique de bir indekstir)?
wkrueger

35

Özenle seçilmiş benzersiz bir Dizin ek açıklamaları koleksiyonu

= Özellikler =

= ORM Çerçeveleri =

= Android için ORM =

= Diğer (kategorize edilmesi zor) =

  • Bölge - iOS / Android için Alternatif Veritabanı: Ek Açıklama io.realm.annotations.Index;
  • Empire-db - JDBC'ye dayalı hafif ama güçlü bir ilişkisel DB soyutlama katmanı. Ek açıklamalarla şema tanımı yoktur;
  • Kotlin NoSQL (GitHub) - NoSQL veritabanları (PoC) ile çalışmak için reaktif ve tip güvenli bir DSL: ???
  • Slick - Scala için Reaktif Fonksiyonel İlişkisel Haritalama. Ek açıklamalarla şema tanımı yoktur.

Sadece bir tanesine git.


31

JPA 2.1 (nihayet) indeksler ve yabancı anahtarlar için destek ekler! Ayrıntılar için bu bloga bakın. JPA 2.1, Java EE 7'nin bir parçasıdır.

Sınırda yaşamayı seviyorsanız, eclipselink'in en son anlık görüntüsünü maven deposundan alabilirsiniz (groupId: org.eclipse.persistence, artifactId: eclipselink, sürüm: 2.5.0-SNAPSHOT). Yalnızca JPA ek açıklamaları için (2.1'i destekledikten sonra herhangi bir sağlayıcıyla çalışması gerekir) artifactID: javax.persistence, sürüm: 2.1.0-SNAPSHOT kullanın.

Yayınlanana kadar bitmeyecek bir proje için kullanıyorum ve herhangi bir korkunç sorun fark etmedim (bununla çok karmaşık bir şey yapmama rağmen).

GÜNCELLEME (26 Eylül 2013): Günümüzde eclipselink'in yayın ve yayın adayı sürümleri merkezi (ana) depoda mevcuttur, bu nedenle artık Maven projelerinde eclipselink havuzunu eklemeniz gerekmez. En son sürüm 2.5.0'dır ancak 2.5.1-RC3 de mevcuttur. 2.5.0 sürümüyle ilgili sorunlar nedeniyle 2.5.1 ASAP'a geçtim (modelgen işleri çalışmıyor).


9

JPA 2.1'de aşağıdakileri yapmanız gerekir

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

Yukarıdaki örnekte TEST_PERSON tablosunun 3 indeksi olacaktır:

  • birincil anahtar kimliğindeki benzersiz dizin

  • AGE endeksi

  • FNAME, SNAME üzerindeki bileşik dizin

Not 1: Bileşik dizini, aynı ada sahip iki @Index ek açıklamasına sahip olarak elde edersiniz.

Not 2: Sütun adını fieldName'de değil, columnList'te belirtirsiniz.


5

Veritabanı dizinlerini standart bir şekilde belirtebilmeyi gerçekten çok isterdim, ancak ne yazık ki bu JPA spesifikasyonunun bir parçası değil (belki de DDL oluşturma desteğinin JPA spesifikasyonu tarafından gerekli olmaması nedeniyle böyle bir özellik).

Yani bunun için sağlayıcıya özel bir uzantıya güvenmeniz gerekecek. Hibernate, OpenJPA ve EclipseLink açıkça böyle bir uzantı sunuyor. DataNucleus için onaylayamıyorum ama indekslerin tanımı JDO'nun bir parçası olduğu için sanırım öyle.

Endeks desteğinin şartnamenin sonraki sürümlerinde standart hale geleceğini umuyorum ve bu nedenle diğer cevaplarla bir şekilde aynı fikirde değilim, JPA'ya böyle bir şeyi dahil etmemek için iyi bir neden görmüyorum (özellikle veritabanı her zaman kontrolünüz altında olmadığından) optimum DDL oluşturma desteği için.

Bu arada, JPA 2.0 özelliklerini indirmenizi öneririm.


4

Bildiğim kadarıyla, dizinleri belirlemenin çapraz JPA Sağlayıcı bir yolu yok. Ancak, bunları her zaman doğrudan veritabanında elle oluşturabilirsiniz, çoğu veritabanı sorgu planlaması sırasında bunları otomatik olarak alır.


2
lol, bu DBA'nın işini yapan DBA'larınız olduğunu varsayarsak (:
Jay

3
"Benzersiz" yapmanın bir yolu olduğunu, ancak bir dizin oluşturmanın bir yolu olmadığını biraz garip buluyorum.
Jay

7
@Jacob - Uygulama düzeyinde bazı alanların benzersiz olup olmayacağını bilmek önemlidir. Öte yandan dizinler db erişimini optimize etmek içindir. Java katmanında bir sütunun indeks olup olmadığını bilmeye (gördüğüm kadarıyla) gerek yok. DBA, belirli bir sütunun bundan fayda sağlayacağını düşünüyorsa, DBA bir dizin oluşturabilir.
Java Drinker

1
@Jacob, Endeks desteği yok çünkü bu sadece bir optimizasyon (genellikle önemli ama yine de bir optimizasyon). Bir alanın (veya alan kümesinin) benzersiz olup olmadığı modele bağlı değilse OTOH ve doğruluğu etkiler. Ayrıca, tam teşekküllü bir 200USD / Hr DBA'ya gerek yoktur, bazı basit dizin oluşturma ifadeleri genellikle yeterlidir.
Tassos Bassoukos

8
JPA 2.1 Belirtiyorjavax.persistence.Index
Lukas Eder

2

EclipseLink , sütunlarda bir indeks tanımlamak için bir açıklama (ör. @Index ) sağladı. Kullanımının bir örneği var . Örneğin bir kısmı dahil edilmiştir ...

FirstName ve lastName alanları birlikte ve ayrı ayrı dizine alınır.

@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, özellikteki dizini tanımlamak için standart olmayan açıklama belirtmenize olanak tanır.

Detaylar burada .



0

Bunu JPA açıklamasını kullanarak yapmak mümkün değildir. Ve bu mantıklı: Bir UniqueConstraint bir iş kuralını açıkça tanımladığında, bir dizin sadece aramayı daha hızlı hale getirmenin bir yoludur. Yani bu gerçekten bir DBA tarafından yapılmalıdır.


0

Bu çözüm EclipseLink 2.5 içindir ve çalışır (test edilmiştir):

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

Bu yükselen sıralamayı varsayar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.