null

Повторяемые аннотации в Java

До появления Java 8 при использовании аннотаций часто возникали проблемы, если необходимо было применить к классу, интерфейсу или полю одну и ту же аннотацию несколько раз. Например, предположим, что мы хотим описать через JPA сущность Студент с двумя NamedQuery. Чтобы обойти эту проблему (до JPA 2.2) необходимо было использовать дополнительную аннотацию (javax.persistence.@NamedQueries):

@Entity
@NamedQueries({
    @NamedQuery(name = “Student.findByName”, query = “SELECT s FROM Student s WHERE s.name = :name”),
    @NamedQuery(name = “Student.findByGroup”, query = “SELECT s FROM Student s WHERE s.group = :group”)
})
public class Student implements Serializable {
    //implementation
}

В Java 8 появилась поддержка повторяемых аннотаций.
Чтобы определить повторяемую аннотацию, необходимо пометить ее определение мета-аннотацией:

import java.lang.annotation.Repeatable;

@Repeatable(Queries.class)
public @interface Query {
    String name() default "someName";
}

@Queries - аннотация-контейнер, для хранения повторяющихся аннотаций. Определение аннотации-контейнера должно содержать value с типом массива необходимой аннотации. Для Query аннотация @Queries может быть определена следующим образом:

public @interface Queries {
    Query[] value();
}

Теперь (начиная с JPA 2.2) пример с сущностью Student можно переписать следующим образом:

@Entity
@NamedQuery(name = “Student.findByName”, query = “SELECT s FROM Student s WHERE s.name = :name”),
@NamedQuery(name = “Student.findByGroup”, query = “SELECT s FROM Student s WHERE s.group = :group”)
public class Student implements Serializable {
    //implementation
}

Это можно сделать благодаря тому, что в JPA 2.2 определение NamedQuery помечено мета-аннотацией @Repeatable:

@Repeatable(NamedQueries.class)
@Target({TYPE})
@Retention(RUNTIME)
public @interface NamedQuery { //implementation }