Указание индекса (неуникального ключа) с помощью JPA

100

Как вы определяете поле, например, 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

Ответы:

208

С 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{
Borjab
источник
Спасибо Элвину за его ответ. (+1 голос). Но мне пришлось поискать кое-что, и я надеюсь, что этот пример может облегчить вам жизнь
Borjab
Именно то, что я искал - простой и чистый код, вырезанный, а не только описывающий все. Спасибо +1.
DominikAngerer
2
@borjab - не могли бы вы подсказать, где я могу найти "официальный" пример или спецификацию использования @Indexаннотации в @Tableаннотации? Я искал на JSR 338, но не нашел там. Ваш пост мне очень пригодился.
Джим Хокинс,
2
@Ulrich Не совсем официальная документация, но блог оракула blogs.oracle.com/arungupta/entry/jpa_2_1_schema_generation
borjab
Интересно, если у меня есть столбец с @Column (unique = true), объединяется ли он со списком индексов (поскольку unique также является индексом)?
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 =

= ORM для Android =

= Другое (сложно категоризировать) =

  • Realm - Альтернативная БД для iOS / Android: Аннотация io.realm.annotations.Index;
  • Empire-db - легкий, но мощный уровень абстракции реляционной БД на основе JDBC. У него нет определения схемы через аннотации;
  • Kotlin NoSQL (GitHub) - реактивный и типобезопасный DSL для работы с базами данных NoSQL (PoC): ???
  • Slick - Реактивное функциональное реляционное отображение для Scala. У него нет определения схемы через аннотации.

Просто выберите один из них.

naXa
источник
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, version: 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: вы указываете имя столбца в columnList, а не fieldName

Джеймс Клейтон
источник
5

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

Поэтому для этого вам придется полагаться на расширение конкретного поставщика. Hibernate, OpenJPA и EclipseLink явно предлагают такое расширение. Я не могу подтвердить для DataNucleus, но поскольку определение индексов является частью JDO, я думаю, что это так.

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

Кстати, предлагаю скачать спецификацию JPA 2.0.

Паскаль Тивент
источник
4

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

Tassos Bassoukos
источник
2
лол, это при условии, что у вас есть администраторы баз данных, которые выполняют работу администраторов баз данных (:
Джейкоб,
3
Мне кажется немного странным, что есть способ сделать "уникальный", но нет способа сделать индекс.
Джейкоб
7
@Jacob - На уровне приложения важно знать, будет ли какое-то поле уникальным или нет. Индексы, с другой стороны, предназначены для оптимизации доступа к БД. Нет необходимости (насколько я понимаю) знать, является ли столбец индексом или нет на уровне java. Как вы сказали, администратор базы данных может создать индекс, если кажется, что это принесет пользу конкретному столбцу.
Java Drinker
1
@Jacob, поддержки индекса нет, потому что это просто оптимизация (обычно важная, но все же оптимизация). OTOH, если поле (или набор полей) является уникальным или нет, зависит от модели и повлияет на правильность. Кроме того, нет необходимости в полноценном администраторе баз данных на 200 долларов в час, обычно достаточно нескольких простых операторов создания индекса.
Tassos Bassoukos,
8
JPA 2.1 определяетjavax.persistence.Index
Лукас Эдер
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 четко определяет бизнес-правила, индекс - это просто способ ускорить поиск. Так что это действительно должен делать администратор базы данных.

Тьерри-Димитри Рой
источник
0

Это решение предназначено для EclipseLink 2.5, и оно работает (проверено):

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

Это предполагает возрастающий порядок.

Джо Алмор
источник