Вказівка ​​індексу (не унікального ключа) за допомогою JPA


98

Як ви визначаєте поле, наприклад 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

Відповіді:


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;

} 

Оновлення : Якщо вам коли-небудь потрібно буде створити та проіндексувати два або більше стовпців, ви можете використовувати коми. Наприклад:

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

Дякую Елвіну за його відповідь. (+1 голос). Але мені довелося шукати кілька речей, і, сподіваюся, цей приклад може полегшити вам життя
borjab

Саме те, що я шукав - простий і чистий вирізаний код - не тільки описуючи все це. Дякую +1.
DominikAngerer

2
@borjab - чи можете ви дати мені підказку, де я можу знайти "офіційний" приклад або специфікацію використання @Indexанотації в @Tableанотації? Я шукав на JSR 338, але там не знайшов. Ваша публікація мені дуже корисна.
JimHawkins

2
@Ulrich Не зовсім офіційна документація, але блог oracle blogs.oracle.com/arungupta/entry/jpa_2_1_schema_generation
борджаб,

Цікаво, якщо у мене є стовпець з @Column (унікальний = істинний), чи він зливається зі списком індексів (оскільки унікальний - це також індекс)?
wkrueger

34

Унікальна колекція анотацій, підібраних вручну

= Технічні характеристики =

  • JPA 2.1 +: javax.persistence.Index(або см JSR-000338 . PDF, стор 452, пункт 11.1.23)
    Угода JPA @Indexанотація може бути використана тільки як частина інших , як анотації @Table, @SecondaryTableі т.д.:

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

= ORM Frameworks =

= ORM для Android =

= Інші (важко класифікувати) =

  • Сфера - Альтернативна БД для iOS / Android: Анотація io.realm.annotations.Index;
  • Empire-db - легкий, але потужний реляційний рівень абстракції БД на основі JDBC. Він не має визначення схеми за допомогою анотацій;
  • Kotlin NoSQL (GitHub) - реактивний і безпечний для типу DSL DSL для роботи з базами даних NoSQL (PoC): ???
  • Гладкореактивне функціональне реляційне картографування для 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 вересня 2013 р.): На сьогодні випуск і випуск кандидатських версій eclipselink доступні в центральному (основному) сховищі, тому вам більше не потрібно додавати сховище eclipselink у проекти Maven. Остання версія 2.5.0, але 2.5.1-RC3 також присутня. Я перейшов би до версії 2.5.1 якомога швидше через проблеми з випуском 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 індекси:

  • унікальний індекс на ідентифікаторі первинного ключа

  • індекс за ВІКОМ

  • складений індекс на FNAME, SNAME

Примітка 1. Складений індекс ви отримуєте, маючи дві анотації @Index з однаковим ім’ям

Примітка 2: Ви вказуєте ім'я стовпця у стовпці ListList, а не fieldName


5

Мені дуже хотілося б мати можливість вказувати індекси баз даних стандартизованим способом, але, на жаль, це не є частиною специфікації JPA (можливо, тому, що підтримка генерації DDL не потрібна в специфікації JPA, що є свого роду перешкодою для така особливість).

Тож вам доведеться покладатися на розширення для цього провайдера. Hibernate, OpenJPA та EclipseLink явно пропонують таке розширення. Я не можу підтвердити для DataNucleus, але оскільки визначення індексів є частиною JDO, я думаю, це так.

Я дуже сподіваюся, що підтримка індексу стандартизуватиметься в наступних версіях специфікації, і, таким чином, якось не погоджуюся з іншими відповідями, я не бачу жодної вагомої причини не включати таке в JPA (тим більше, що база даних не завжди знаходиться під вашим контролем) для оптимальної підтримки генерації DDL.

До речі, я пропоную завантажити специфікацію JPA 2.0.


4

Наскільки я знаю, не існує перехресного провайдера JPA-способу вказати індекси. Однак ви завжди можете створити їх вручну безпосередньо в базі даних, більшість баз даних автоматично їх підбирають під час планування запитів.


2
ха-ха, це припускаючи, що у вас є DBA, які виконують роботу DBA (:
Jacob

3
Мені здається трохи дивним, що існує спосіб зробити "унікальний", але не спосіб зробити індекс.
Яків

7
@Jacob - Ну, важливо знати на рівні програми, чи буде якесь поле унікальним чи ні. З іншого боку, індекси призначені для цілей оптимізації доступу до баз даних. Немає необхідності (наскільки я бачу) знати, є стовпець індексом чи ні на рівні Java. Як ви вже сказали, DBA може встановити індекс, якщо здається, що певний стовпець виграє від цього.
Java Drinker

1
@Jacob, немає підтримки індексу, оскільки це просто оптимізація (зазвичай важлива, але все одно оптимізація). OTOH, якщо поле (або набір полів) є унікальним чи ні, залежить від моделі та вплине на правильність. Крім того, немає необхідності в повноцінному DBA 200USD / Hr, деяких простих операторів створення індексу зазвичай буває достатньо.
Тассос Бассукос,


2

EclipseLink надав анотацію (наприклад, @Index ) для визначення індексу в стовпцях. Є приклад його використання. Частина прикладу включена ...

Поля Ім'я та Прізвище індексуються разом та окремо.

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

Це передбачає порядок зростання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.