Chỉ định một chỉ mục (Khóa không phải duy nhất) bằng JPA


98

Làm thế nào để bạn xác định một trường, chẳng hạn emailnhư có một chỉ mục bằng cách sử dụng chú thích JPA. Chúng tôi cần một khóa không phải là duy nhất emailvì có hàng triệu truy vấn trên trường này mỗi ngày và nó hơi chậm nếu không có khóa.

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

Tôi đã thấy một chú thích cụ thể về chế độ ngủ đông nhưng tôi đang cố gắng tránh các giải pháp cụ thể của nhà cung cấp vì chúng tôi vẫn đang quyết định giữa chế độ ngủ đông và hạt nhân dữ liệu.

CẬP NHẬT:

Đối với JPA 2.1, bạn có thể làm điều này. Xem: Chú thích @Index không được phép cho vị trí này


6
Tôi sẽ là tuyệt vời nếu bạn có thể cập nhật các câu trả lời để mọi người thấy rằng với JPA 2.1 có thực sự là một cách để làm điều đó
borjab

2
Tại sao bạn không chấp nhận câu trả lời được ủng hộ nhiều nhất?
naXa

Câu trả lời:


206

Với JPA 2.1, bạn sẽ có thể làm được.

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;

} 

Cập nhật : Nếu bạn cần tạo và lập chỉ mục với hai hoặc nhiều cột, bạn có thể sử dụng dấu phẩy. Ví dụ:

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

Cảm ơn Alvin vì câu trả lời của anh ấy. (+1 phiếu bầu). Nhưng tôi đã phải tìm một vài điều tôi hy vọng một ví dụ này có thể làm cho cuộc sống của bạn dễ dàng hơn
borjab

Chính xác những gì tôi đang tìm kiếm - một đoạn mã đơn giản và sạch sẽ - không chỉ mô tả toàn bộ. Cảm ơn +1.
DominikAngerer

2
@borjab - bạn có thể vui lòng cho tôi gợi ý về nơi tôi có thể tìm thấy một ví dụ hoặc thông số kỹ thuật "chính thức" để sử dụng @Indexchú thích trong @Tablechú thích không? Tôi đã tìm kiếm trên JSR 338 nhưng tôi không tìm thấy nó ở đó. Bài viết của bạn rất hữu ích đối với tôi.
JimHawkins

2
@Ulrich Không chính xác documentatio nhưng blog của oracle chính thức blogs.oracle.com/arungupta/entry/jpa_2_1_schema_generation
borjab

Tôi tự hỏi, nếu tôi có một cột với @Column (duy nhất = true), nó có được hợp nhất vào danh sách chỉ mục (vì duy nhất cũng là một chỉ mục) không?
wkrueger

34

Bộ sưu tập chú thích chỉ mục được chọn lọc thủ công độc đáo

= Thông số kỹ thuật =

= Khung ORM =

= ORM cho Android =

= Khác (khó phân loại) =

  • Realm - Thay thế DB cho iOS / Android: Chú thích io.realm.annotations.Index;
  • Empire-db - một lớp trừu tượng DB quan hệ nhẹ nhưng mạnh mẽ dựa trên JDBC. Nó không có định nghĩa lược đồ thông qua các chú thích;
  • Kotlin NoSQL (GitHub) - một DSL phản ứng và an toàn kiểu để làm việc với cơ sở dữ liệu NoSQL (PoC): ???
  • Slick - Bản đồ quan hệ chức năng phản ứng cho Scala. Nó không có định nghĩa lược đồ thông qua các chú thích.

Chỉ cần đi cho một trong số họ.


31

JPA 2.1 (cuối cùng) bổ sung hỗ trợ cho các chỉ mục và khóa ngoại! Xem blog này để biết chi tiết. JPA 2.1 là một phần của Java EE 7, đã ra mắt.

Nếu bạn thích sống ẩn dật, bạn có thể lấy ảnh chụp nhanh mới nhất cho liên kết nhật thực từ kho lưu trữ maven (groupId: org.eclipse.persistence, craftId: eclipselink, phiên bản: 2.5.0-SNAPSHOT). Đối với chỉ các chú thích JPA (sẽ hoạt động với bất kỳ nhà cung cấp nào khi họ hỗ trợ 2.1), hãy sử dụng ArtiID: javax.persistence, phiên bản: 2.1.0-SNAPSHOT.

Tôi đang sử dụng nó cho một dự án sẽ không hoàn thành cho đến sau khi phát hành và tôi không nhận thấy bất kỳ vấn đề kinh khủng nào (mặc dù tôi không làm bất cứ điều gì quá phức tạp với nó).

CẬP NHẬT (26 tháng 9 năm 2013): Phiên bản ứng viên của eclipselink ngày nay đã có sẵn trong kho lưu trữ trung tâm (chính), vì vậy bạn không còn phải thêm kho lưu trữ liên kết nhật bản trong các dự án Maven. Phiên bản phát hành mới nhất là 2.5.0 nhưng 2.5.1-RC3 cũng có mặt. Tôi muốn chuyển sang 2.5.1 càng sớm càng tốt vì các vấn đề với bản phát hành 2.5.0 (công cụ modelgen không hoạt động).


9

Trong JPA 2.1, bạn cần làm như sau

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

Trong ví dụ trên, bảng TEST_PERSON sẽ có 3 chỉ mục:

  • chỉ mục duy nhất trên ID khóa chính

  • chỉ số về AGE

  • chỉ mục kết hợp trên FNAME, SNAME

Lưu ý 1: Bạn nhận được chỉ mục kết hợp bằng cách có hai chú thích @Index có cùng tên

Lưu ý 2: Bạn chỉ định tên cột trong columnList không phải fieldName


5

Tôi thực sự muốn có thể chỉ định các chỉ mục cơ sở dữ liệu theo cách chuẩn hóa, nhưng thật đáng buồn, đây không phải là một phần của đặc tả JPA (có thể vì đặc tả JPA không yêu cầu hỗ trợ tạo DDL, đây là một loại đường chặn cho một tính năng).

Vì vậy, bạn sẽ phải dựa vào tiện ích mở rộng dành riêng cho nhà cung cấp cho việc đó. Hibernate, OpenJPA và EclipseLink rõ ràng cung cấp một phần mở rộng như vậy. Tôi không thể xác nhận cho DataNucleus nhưng vì định nghĩa chỉ mục là một phần của JDO, tôi đoán là có.

Tôi thực sự hy vọng hỗ trợ chỉ mục sẽ được chuẩn hóa trong các phiên bản tiếp theo của thông số kỹ thuật và do đó, bằng cách nào đó không đồng ý với các câu trả lời khác, tôi không thấy có lý do chính đáng nào để không đưa một thứ như vậy vào JPA (đặc biệt là vì cơ sở dữ liệu không phải lúc nào cũng nằm trong tầm kiểm soát của bạn) để hỗ trợ tạo DDL tối ưu.

Nhân tiện, tôi khuyên bạn nên tải xuống thông số kỹ thuật JPA 2.0.


4

Theo như tôi biết, không có cách Nhà cung cấp JPA chéo để chỉ định các chỉ mục. Tuy nhiên, bạn luôn có thể tạo chúng bằng tay trực tiếp trong cơ sở dữ liệu, hầu hết các cơ sở dữ liệu sẽ tự động chọn chúng trong quá trình lập kế hoạch truy vấn.


2
lol, giả sử bạn có DBA thực hiện công việc của một DBA (:
Jacob

3
Tôi thấy hơi kỳ lạ khi có một cách để thực hiện "duy nhất" nhưng không phải là một cách để thực hiện một chỉ mục.
Jacob

7
@Jacob - Điều quan trọng là phải biết ở cấp ứng dụng liệu một số trường có phải là duy nhất hay không. Mặt khác, các chỉ mục nhằm mục đích tối ưu hóa việc truy cập db. Không cần (theo như tôi thấy) để biết liệu một cột có phải là một chỉ mục hay không ở lớp java. Giống như bạn đã nói, DBA có thể thiết lập chỉ mục nếu có vẻ như một cột cụ thể sẽ được hưởng lợi từ nó.
Java Drinker

1
@Jacob, không có Index suport vì đó chỉ đơn giản là tối ưu hóa (thường là tối ưu hóa, nhưng vẫn là tối ưu hóa). OTOH nếu một trường (hoặc tập hợp các trường) là duy nhất hay không phụ thuộc vào mô hình và sẽ ảnh hưởng đến tính đúng đắn. Ngoài ra, không cần DBA 200USD / Hr chính thức, một số câu lệnh tạo chỉ mục đơn giản thường là đủ.
Tassos Bassoukos

8
JPA 2.1 Chỉ địnhjavax.persistence.Index
Lukas Eder

2

EclipseLink đã cung cấp một chú thích (ví dụ: @Index ) để xác định một chỉ mục trên các cột. Có một ví dụ về việc sử dụng nó. Một phần của ví dụ được bao gồm ...

Trường firstName và lastName được lập chỉ mục, cùng nhau và riêng lẻ.

@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 cho phép bạn chỉ định chú thích không chuẩn để xác định chỉ mục trên thuộc tính.

Thông tin chi tiết có tại đây .



0

Không thể làm điều đó bằng cách sử dụng chú thích JPA. Và điều này có ý nghĩa: trong đó UniqueConstraint xác định rõ ràng các quy tắc kinh doanh, một chỉ mục chỉ là một cách giúp tìm kiếm nhanh hơn. Vì vậy, điều này thực sự nên được thực hiện bởi một DBA.


0

Giải pháp này dành cho EclipseLink 2.5 và nó hoạt động (đã được thử nghiệm):

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

Điều này giả định thứ tự tăng dần.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.