การระบุดัชนี (คีย์ที่ไม่ซ้ำกัน) โดยใช้ JPA


102

คุณกำหนดเขตข้อมูลได้อย่างไรเช่นemailการมีดัชนีโดยใช้คำอธิบายประกอบ JPA เราต้องการคีย์ที่ไม่ซ้ำกัน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 ไม่ได้รับอนุญาตสำหรับตำแหน่งนี้


6
ฉันจะดีมากถ้าคุณสามารถอัปเดตคำตอบเพื่อให้ผู้คนพบว่าด้วย JPA 2.1 มีวิธีที่จะทำได้จริงๆ
borjab

2
ทำไมคุณไม่ยอมรับคำตอบที่โหวตมากที่สุด?
naXa

คำตอบ:


215

ด้วย 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{

ขอบคุณ Alvin สำหรับคำตอบของเขา (+1 โหวต) แต่ฉันต้องมองหาบางสิ่งฉันหวังว่าตัวอย่างนี้อาจทำให้ชีวิตของคุณง่ายขึ้น
borjab

สิ่งที่ฉันกำลังมองหานั่นคือโค้ดที่เรียบง่ายและสะอาดตา - ไม่เพียง แต่อธิบายเรื่องทั้งหมด ขอบคุณ +1
DominikAngerer

2
@borjab - คุณช่วยให้คำแนะนำได้ไหมว่าฉันจะหาตัวอย่าง "อย่างเป็นทางการ" หรือข้อกำหนดสำหรับการใช้@Indexคำอธิบายประกอบภายใน@Tableคำอธิบายประกอบได้หรือไม่ ฉันค้นหาด้วยJSR 338แต่ไม่พบที่นั่น โพสต์ของคุณมีประโยชน์กับฉันมาก
JimHawkins

2
@Ulrich ไม่ใช่เอกสารอย่างเป็นทางการ แต่บล็อกของ oracle blogs.oracle.com/arungupta/entry/jpa_2_1_schema_generation
borjab

ฉันสงสัยว่าถ้าฉันมีคอลัมน์ที่มี @Column (unique = true) มันจะรวมเข้ากับรายการดัชนี (เนื่องจาก unique เป็นดัชนีด้วย)
wkrueger

35

คอลเลคชันคำอธิบายประกอบดัชนีที่คัดสรรมาด้วยมืออันเป็นเอกลักษณ์

= ข้อมูลจำเพาะ =

  • JPA 2.1 +: javax.persistence.Index(หรือดูJSR-000338 . PDF, P 452 รายการ 11.1.23)
    JPA @Indexคำอธิบายประกอบสามารถนำมาใช้เป็นส่วนหนึ่งของคำอธิบายประกอบอีกเช่นเพียง@Table, @SecondaryTableฯลฯ .:

    @Table(indexes = { @Index(...) })
    
  • JDO 2.1+:javax.jdo.annotations.Index

= กรอบORM =

= ORM สำหรับAndroid =

= อื่น ๆ (จัดหมวดหมู่ยาก) =

  • Realm - ฐานข้อมูลทางเลือกสำหรับ iOS / Android: คำอธิบายประกอบio.realm.annotations.Index;
  • Empire-db - เลเยอร์ Abstraction DB เชิงสัมพันธ์ที่มีน้ำหนักเบา แต่ทรงพลังบนพื้นฐานของ JDBC ไม่มีข้อกำหนดสคีมาผ่านคำอธิบายประกอบ
  • Kotlin NoSQL (GitHub) - DSL แบบตอบสนองและปลอดภัยสำหรับการทำงานกับฐานข้อมูล NoSQL (PoC): ???
  • Slick - การทำแผนที่เชิงสัมพันธ์เชิงฟังก์ชันเชิงปฏิกิริยาสำหรับ Scala ไม่มีข้อกำหนดสคีมาผ่านคำอธิบายประกอบ

เพียงแค่เลือกหนึ่งในนั้น


31

JPA 2.1 (ในที่สุด) เพิ่มการรองรับดัชนีและคีย์ต่างประเทศ! ดูรายละเอียดในบล็อกนี้ JPA 2.1 เป็นส่วนหนึ่งของ Java EE 7 ซึ่งออก

หากคุณชอบใช้ชีวิตบนขอบคุณสามารถรับสแนปช็อตล่าสุดสำหรับ eclipselink ได้จากที่เก็บ maven (groupId: org.eclipse.persistence, artifactId: eclipselink, เวอร์ชัน: 2.5.0-SNAPSHOT) สำหรับคำอธิบายประกอบ JPA (ซึ่งควรทำงานร่วมกับผู้ให้บริการรายใดก็ได้เมื่อรองรับ 2.1) ให้ใช้ artifactID: javax.persistence เวอร์ชัน: 2.1.0-SNAPSHOT

ฉันกำลังใช้มันสำหรับโปรเจ็กต์ที่จะไม่เสร็จจนกว่าจะวางจำหน่ายและฉันไม่ได้สังเกตเห็นปัญหาที่น่ากลัวใด ๆ (แม้ว่าฉันจะไม่ได้ทำอะไรที่ซับซ้อนเกินไปก็ตาม)

อัปเดต (26 ก.ย. 2556): ปัจจุบัน eclipselink รุ่นที่วางจำหน่ายและเผยแพร่มีอยู่ในที่เก็บส่วนกลาง (หลัก) ดังนั้นคุณจึงไม่ต้องเพิ่มที่เก็บ eclipselink ในโครงการ Maven อีกต่อไป เวอร์ชันล่าสุดคือ 2.5.0 แต่มี 2.5.1-RC3 ด้วย ฉันจะเปลี่ยนไปใช้ 2.5.1 ASAP เนื่องจากมีปัญหากับรุ่น 2.5.0 (สิ่งที่ 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 ดัชนี:

  • ดัชนีเฉพาะในรหัสคีย์หลัก

  • ดัชนีใน AGE

  • ดัชนีผสมบน FNAME, SNAME

หมายเหตุ 1: คุณได้รับดัชนีผสมโดยมีคำอธิบายประกอบ @Index สองรายการที่มีชื่อเดียวกัน

หมายเหตุ 2: คุณระบุชื่อคอลัมน์ใน columnList ไม่ใช่ fieldName


5

ฉันต้องการระบุดัชนีฐานข้อมูลด้วยวิธีที่เป็นมาตรฐาน แต่น่าเสียดายที่นี่ไม่ใช่ส่วนหนึ่งของข้อกำหนด JPA (อาจเป็นเพราะข้อกำหนด JPA ไม่จำเป็นต้องรองรับการสร้าง DDL ซึ่งเป็นบล็อกถนนสำหรับ คุณสมบัติดังกล่าว)

ดังนั้นคุณจะต้องพึ่งพาส่วนขยายเฉพาะของผู้ให้บริการสำหรับสิ่งนั้น Hibernate, OpenJPA และ EclipseLink เสนอส่วนขยายดังกล่าวอย่างชัดเจน ฉันไม่สามารถยืนยันสำหรับ DataNucleus ได้ แต่เนื่องจากนิยามดัชนีเป็นส่วนหนึ่งของ JDO ฉันคิดว่ามันเป็นเช่นนั้น

ฉันหวังว่าการสนับสนุนดัชนีจะได้รับมาตรฐานในข้อกำหนดเวอร์ชันถัดไปดังนั้นจึงไม่เห็นด้วยกับคำตอบอื่น ๆ ฉันไม่เห็นเหตุผลที่ดีที่จะไม่รวมสิ่งดังกล่าวไว้ใน JPA (โดยเฉพาะอย่างยิ่งเนื่องจากฐานข้อมูลไม่ได้อยู่ภายใต้การควบคุมของคุณเสมอไป) สำหรับการสนับสนุนการสร้าง DDL ที่ดีที่สุด

ยังไงก็ตามฉันขอแนะนำให้ดาวน์โหลดข้อมูลจำเพาะ JPA 2.0


4

เท่าที่ฉันทราบไม่มีวิธีข้ามผู้ให้บริการ JPA ในการระบุดัชนี อย่างไรก็ตามคุณสามารถสร้างด้วยมือโดยตรงในฐานข้อมูลได้เสมอโดยฐานข้อมูลส่วนใหญ่จะหยิบขึ้นมาโดยอัตโนมัติในระหว่างการวางแผนแบบสอบถาม


2
ฮ่า ๆ สมมติว่าคุณมี DBA ที่ทำหน้าที่ของ DBA ได้ (:
Jay

3
ฉันคิดว่ามันแปลกเล็กน้อยที่มีวิธีทำ "เฉพาะ" แต่ไม่ใช่วิธีทำดัชนี
เจ

7
@Jacob - สิ่งสำคัญคือต้องรู้ในระดับแอปพลิเคชันว่าบางฟิลด์จะไม่ซ้ำกันหรือไม่ ในทางกลับกันดัชนีมีไว้เพื่อจุดประสงค์ในการเพิ่มประสิทธิภาพการเข้าถึงฐานข้อมูล ไม่มีความจำเป็น (เท่าที่ฉันเห็น) ที่จะรู้ว่าคอลัมน์เป็นดัชนีหรือไม่ที่เลเยอร์ java อย่างที่คุณพูด DBA สามารถตั้งค่าดัชนีได้หากดูเหมือนว่าคอลัมน์ใดคอลัมน์หนึ่งจะได้รับประโยชน์จากมัน
Java Drinker

1
@Jacob ไม่มีดัชนี suport เพราะนั่นเป็นเพียงการเพิ่มประสิทธิภาพ (โดยปกติจะเป็นสิ่งที่สำคัญ แต่ยังคงเป็นการเพิ่มประสิทธิภาพ) OTOH หากฟิลด์ (หรือชุดของฟิลด์) ไม่ซ้ำกันหรือไม่ขึ้นอยู่กับรุ่นและจะส่งผลต่อความถูกต้อง นอกจากนี้ไม่จำเป็นต้องมี DBA 200USD / Hr ที่เต็มเปี่ยมด้วยงบสร้างดัชนีง่ายๆบางอย่างก็เพียงพอแล้ว
Tassos Bassoukos

8
JPA 2.1 ระบุjavax.persistence.Index
Lukas Eder

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 อนุญาตให้คุณระบุคำอธิบายประกอบที่ไม่ได้มาตรฐานเพื่อกำหนดดัชนีในคุณสมบัติ

โดยมีรายละเอียดที่นี่


1

เพื่อสรุปคำตอบอื่น ๆ :

ฉันจะไปหาหนึ่งในนั้น มันจะมาพร้อมกับ JPA 2.1 อยู่ดีและไม่ควรเปลี่ยนยากเกินไปในกรณีที่คุณต้องการเปลี่ยนผู้ให้บริการ JPA ของคุณจริงๆ


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.