3.2.1.2.2. Аннотации атрибутов

Аннотации атрибутов устанавливаются на соответствующие поля класса, за одним исключением: если требуется объявить неизменяемый (read only) неперсистентный атрибут foo, то достаточно создать метод доступа getFoo() и поместить на этот метод аннотацию @MetaProperty.

@CaseConversion

Применяет автоматическую конвертацию регистра к текстовым полям ввода, связанным с аннотированным атрибутом.

Параметры:

  • type - тип конвертации: UPPER (по умолчанию), LOWER.

Пример:

@CaseConversion(type = ConversionType.UPPER)
@Column(name = "COUNTRY_CODE")
protected String countryCode;
@Column

Определяет колонку БД, в которой будут храниться значения данного атрибута.

Параметры:

  • name - имя колонки

  • length - (необязательный параметр, по умолчанию 255) - длина колонки. Используется также при формировании метаданных и, в конечном счете, может ограничивать максимальную длину вводимого текста в визуальных компонентах, работающих с данным атрибутом. Для отмены ограничения по длине атрибуту необходимо добавить аннотацию @Lob.

  • nullable - (необязательный параметр, по умолчанию true) - может ли атрибут содержать null. При указании nullable = false JPA контролирует наличие значения поля при сохранении, кроме того, визуальные компоненты, работающие с данным атрибутом, могут сигнализировать пользователю о необходимости ввода значения.

@Composition

Указывает на то, что связь является композицией - более тесным вариантом ассоциации. Это означает, что связанная сущность имеет смысл только как часть владеющей сущности, т.е. создается и удаляется вместе с ней.

В руководстве Data Modelling: Composition приведены примеры композиции между сущностями.

Например, список пунктов в заказе (класс Order содержит коллекцию экземпляров Item):

@OneToMany(mappedBy = "order")
@Composition
protected List<Item> items;

Другой пример - one-to-one отношение:

@Composition
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "DETAILS_ID")
protected CustomerDetails details;

Указание для связи аннотации @Composition позволяет организовать в экранах редактирования специальный режим коммита источников данных, при котором изменения экземпляров детализирующей сущности сохраняются в базе данных только при коммите основной сущности. Подробнее см. Редактирование композитных сущностей.

@CurrencyValue

Указывает, что данный атрибут предназначен для хранения денежных единиц. Если указана эта аннотация, при генерации экрана редактирования сущности в Studio внутри Form будет автоматически использован компонент CurrencyField.

Параметры:

  • currency – текст, который будет отображаться в ярлыке валюты: например, USD, GBP, EUR, $.

  • labelPosition - определяет положение ярлыка внутри текстового поля: RIGHT (по умолчанию), LEFT.

Пример:

@CurrencyValue(currency = "$", labelPosition = CurrencyLabelPosition.LEFT)
@Column(name = "PRICE")
protected BigDecimal price;
@Embedded

Определяет атрибут типа встраиваемой сущности, в свою очередь аннотированной @Embeddable.

Пример:

@Embedded
protected Address address;
@EmbeddedParameters

По умолчанию ORM не создает экземпляр встроенной сущности если все ее атрибуты равны null в базе данных. Аннотацию @EmbeddedParameters можно использовать для указания того, что экземпляр всегда должен создаваться, например:

@Embedded
@EmbeddedParameters(nullAllowed = false)
protected Address address;
@Id

Указывает, что данный атрибут является первичным ключом сущности. Обычно эта аннотация присутствует на поле базового класса, такого как BaseUuidEntity. Использовать эту аннотацию в конкретном классе сущности необходимо только при наследовании от базового класса BaseStringIdEntity (то есть при создании сущности со строковым первичным ключом).

@IgnoreUserTimeZone

Для атрибутов типа timestamp с аннотацией @javax.persistence.Temporal.TIMESTAMP заставляет платформу игнорировать часовой пояс пользователя, если он задан для текущей сессии.

@JoinColumn

Используется для указания колонки БД, определяющей ассоциацию между сущностями. Наличие этой аннотации указывает, что данная сторона отношения является владеющей (owning).

Параметры:

  • name - имя колонки

Пример:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CUSTOMER_ID")
protected Customer customer;
@JoinTable

Используется для указания таблицы связи на ведущей стороне @ManyToMany ассоциации.

Параметры:

  • name - имя таблицы связи

  • joinColumns - элемент @JoinColumn, определяющий колонку таблицы связей, соответствующую первичному ключу ведущей стороны ассоциации (т.е. содержащей аннотацию @JoinTable)

  • inverseJoinColumns - элемент @JoinColumn, определяющий колонку таблицы связей, соответствующую первичному ключу ведомой стороны ассоциации

Пример атрибута customers класса Group, являющегося ведущей стороной ассоциации:

@ManyToMany
@JoinTable(name = "SALES_CUSTOMER_GROUP_LINK",
  joinColumns = @JoinColumn(name = "GROUP_ID"),
  inverseJoinColumns = @JoinColumn(name = "CUSTOMER_ID"))
protected Set<Customer> customers;

Пример атрибута groups класса Customer, являющегося ведомой стороной этой же ассоциации:

@ManyToMany(mappedBy = "customers")
protected Set<Group> groups;
@Lob

Указывает, что данный атрибут не имеет ограничений длины. Применяется совместно с аннотацией @Column. Если @Lob указан, то длина, заданная в @Column явно или по умолчанию, игнорируется.

Пример:

@Column(name = "DESCRIPTION")
@Lob
private String description;
@Lookup

Определяет тип просмотра ссылочных атрибутов.

Параметры:

  • type - по умолчанию имеет значение SCREEN, при котором ссылки открываются через lookup-экран. Значение DROPDOWN позволяет открывать ссылки в виде выпадающего списка. Если за способ отображения выбран DROPDOWN, Studio создаст options collection container для выпадающего списка при генерации экрана редактирования. Таким образом, параметр Lookup type необходимо задать ДО генерации экрана редактирования сущности. Кроме того, компонент Filter позволит пользователям выбирать параметры фильтрации также из выпадающего списка вместо lookup-экрана.

  • actions - определяет действия, которые будут использованы в компоненте PickerField в составе FieldGroup по умолчанию. Возможные значения: lookup, clear, open.

@Lookup(type = LookupType.DROPDOWN, actions = {"open"})
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CUSTOMER_ID")
protected Customer customer;
@ManyToMany

Определяет атрибут-коллекцию ссылок на сущность с типом ассоциации много-ко-многим.

Руководство Data Modelling: Many-to-Many Association демонстрирует различные варианты использования ассоциаций many-to-many.

Ассоциация много-ко-многим может иметь ведущую сторону и обратную - ведомую. На ведущей стороне указывается дополнительная аннотация @JoinTable, на ведомой стороне - параметр mappedBy.

Параметры:

  • mappedBy - поле связанной сущности, определяющее ассоциацию с ведущей стороны. Необходимо указывать только на ведомой стороне.

  • targetEntity - тип связанной сущности. Необязательный параметр, если коллекция объявлена с использованием Java generics.

  • fetch - (необязательный параметр, по умолчанию LAZY) - определяет, будет ли JPA жадно загружать коллекцию связанных сущностей. Необходимо всегда оставлять значение по умолчанию LAZY, так как в CUBA-приложении политика загрузки связей определяется динамически на основе механизма представлений.

Использование параметра cascade аннотации не рекомендуется. Сущности, сохраняемые неявно при использовании такого объявления, будут пропущены некоторыми системными механизмами. В частности, бин EntityStates некорректно определяет для них состояние managed, а entity listeners не вызываются вообще.

@ManyToOne

Определяет атрибут-ссылку на сущность с типом ассоциации много-к-одному.

Параметры:

  • fetch - (по умолчанию EAGER) параметр, определяющий, будет ли JPA жадно загружать ассоциированную сущность. Данный параметр всегда должен быть установлен в значение LAZY, так как в CUBA-приложении политика загрузки связей определяется динамически на основе механизма представлений.

  • optional - (необязательный параметр, по умолчанию true) - может ли атрибут содержать null. При указании optional = false JPA контролирует наличие ссылки при сохранении, кроме того, визуальные компоненты, работающие с данным атрибутом, могут сигнализировать пользователю о необходимости ввода значения.

Например, несколько экземпляров Order (заказов) ссылаются на один экземпляр Customer (покупателя), в этом случае класс Order должен содержать следующее объявление:

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CUSTOMER_ID")
protected Customer customer;

Использование параметра cascade аннотации не рекомендуется. Сущности, сохраняемые неявно при использовании такого объявления, будут пропущены некоторыми системными механизмами. В частности, бин EntityStates некорректно определяет для них состояние managed, а entity listeners не вызываются вообще.

@MetaProperty

Указывает, что данный атрибут должен быть включен в метаданные. Данная аннотация может быть установлена как на поле класса, так и на метод доступа, в случае отсутствия соответствующего атрибуту поля.

Данная аннотация не обязательна для полей, снабженных следующими аннотациями пакета javax.persistence: @Column, @OneToOne, @OneToMany, @ManyToOne, @ManyToMany, @Embedded. Такие поля отражаются в метаданных автоматически. Поэтому @MetaProperty в основном применяется для определения неперсистентных атрибутов сущностей.

Параметры (опционально):

  • mandatory - может ли атрибут содержать null. При указании mandatory = true визуальные компоненты, работающие с данным атрибутом, могут сигнализировать пользователю о необходимости ввода значения.

  • datatype - явно задает datatype, чтобы переопределить datatype задаваемый Java-типом атрибута.

  • related - задает массив связанных персистентных атрибутов, которые должны быть загружены из БД, если данный атрибут включен в представление. Кроме того, если аннотация указана на методе-геттере, то есть атрибут сущности предназначен только для чтения, то изменения связанных атрибутов генерируют PropertyChangeEvent для данного неизменяемого атрибута. Эта особенность позволяет обновлять UI-компоненты, отображающие неизменяемые атрибуты, зависящие от других изменяемых атрибутов.

Пример использования для поля:

@Transient
@MetaProperty
protected String token;

Пример использования для метода:

@MetaProperty(related = "firstName,lastName")
public String getFullName() {
    return firstName + " " + lastName;
}
@NumberFormat

Задает формат атрибута типа Number (это может быть BigDecimal, Integer, Long или Double). Значения такого атрибута будут форматироваться в пользовательском интерфейсе в соответствии с указанными параметрами аннотации:

  • pattern - паттерн форматирования, задается по правилам, описанным в DecimalFormat.

  • decimalSeparator - символ, используемый в качестве разделителя целой и дробной части (опционально).

  • groupingSeparator - символ, используемый в качестве разделителя групп разрядов (optional).

Если decimalSeparator и/или groupingSeparator не указаны, фреймворк использует соответствующие значения из format strings для локали текущего пользователя. При форматировании без учета локали в этом случае используются символы из системной локали сервера.

Примеры:

@Column(name = "PRECISE_NUMBER", precision = 19, scale = 4)
@NumberFormat(pattern = "0.0000")
protected BigDecimal preciseNumber;

@Column(name = "WEIRD_NUMBER", precision = 19, scale = 4)
@NumberFormat(pattern = "#,##0.0000", decimalSeparator = "_", groupingSeparator = "`")
protected BigDecimal weirdNumber;

@Column(name = "SIMPLE_NUMBER")
@NumberFormat(pattern = "#")
protected Integer simpleNumber;

@Column(name = "PERCENT_NUMBER", precision = 19, scale = 4)
@NumberFormat(pattern = "#%")
protected BigDecimal percentNumber;
@OnDelete

Определяет политику обработки связи в случае мягкого удаления сущности, содержащей данный атрибут. См. Мягкое удаление.

Пример:

@OneToMany(mappedBy = "group")
@OnDelete(DeletePolicy.CASCADE)
private Set<Constraint> constraints;
@OnDeleteInverse

Определяет политику обработки связи в случае мягкого удаления сущности с обратной стороны ассоциации. См. Мягкое удаление.

Пример:

@ManyToOne
@JoinColumn(name = "DRIVER_ID")
@OnDeleteInverse(DeletePolicy.DENY)
private Driver driver;
@OneToMany

Определяет атрибут-коллекцию ссылок на сущность с типом ассоциации один-ко-многим.

Параметры:

  • mappedBy - поле связанной сущности, определяющее ассоциацию

  • targetEntity - тип связанной сущности. Необязательный параметр, если коллекция объявлена с использованием Java generics.

  • fetch - (необязательный параметр, по умолчанию LAZY) - определяет, будет ли JPA жадно загружать коллекцию связанных сущностей. Необходимо всегда оставлять значение по умолчанию LAZY, так как в CUBA-приложении политика загрузки связей определяется динамически на основе механизма представлений.

  • cascade - (необязательный параметр, по умолчанию {}) - каскадирование операций определяет, какие операции над сущностью должны быть применены к ассоциированным сущностям. Каскадирование на данном уровне не рекомендуется использовать.

Например, несколько экземпляров Item (пунктов заказа) ссылаются на один экземпляр Order (заказ) с помощью @ManyToOne поля Item.order, в этом случае класс Order может содержать коллекцию экземпляров Item:

@OneToMany(mappedBy = "order")
protected Set<Item> items;

Использование параметра cascade аннотации не рекомендуется. Сущности, сохраняемые неявно при использовании такого объявления, будут пропущены некоторыми системными механизмами. В частности, бин EntityStates некорректно определяет для них состояние managed, а entity listeners не вызываются вообще. Параметр orphanRemoval не принимает во внимание механизм мягкого удаления.

@OneToOne

Определяет атрибут-ссылку на сущность с типом ассоциации один-к-одному.

Параметры:

  • fetch - (по умолчанию EAGER) параметр, определяющий, будет ли JPA жадно загружать ассоциированную сущность. Данный параметр всегда должен быть установлен в значение LAZY, так как в CUBA-приложении политика загрузки связей определяется динамически на основе механизма представлений.

  • mappedBy - поле связанной сущности, определяющее ассоциацию. Требуется устанавливать только на ведомой стороне ассоциации.

  • optional - (необязательный параметр, по умолчанию true) - может ли атрибут содержать null. При указании optional = false JPA контролирует наличие ссылки при сохранении, кроме того, визуальные компоненты, работающих с данным атрибутом, могут сигнализировать пользователю о необходимости ввода значения.

Пример ведущей стороны ассоциации, класс Driver:

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CALLSIGN_ID")
protected DriverCallsign callsign;

Пример ведомой стороны ассоциации, класс DriverCallsign:

@OneToOne(fetch = FetchType.LAZY, mappedBy = "callsign")
protected Driver driver;
@OrderBy

Определяет порядок элементов в атрибуте-коллекции на момент извлечения из базы данных. Данную аннотацию необходимо задавать для упорядоченных коллекций, таких как List или LinkedHashSet для получения предсказуемого порядка следования элементов.

Параметры:

  • value - строка, определяющая порядок, в формате:

    orderby_list::= orderby_item [,orderby_item]*
    orderby_item::= property_or_field_name [ASC | DESC]

Пример:

@OneToMany(mappedBy = "user")
@OrderBy("createTs")
protected List<UserRole> userRoles;
@Temporal

Для атрибута типа java.util.Date уточняет тип хранимого значения: дата, время или дата+время.

Параметры:

  • value - тип хранимого значения: DATE, TIME, TIMESTAMP

Пример:

@Column(name = "START_DATE")
@Temporal(TemporalType.DATE)
protected Date startDate;
@Transient

Указывает, что данное поле не хранится в БД, т.е. является неперсистентным.

Поля поддерживаемых JPA типов (см. http://docs.oracle.com/javaee/7/api/javax/persistence/Basic.html) по умолчанию являются персистентными, поэтому аннотация @Transient обязательна для объявления неперсистентного атрибута такого типа.

Для включения @Transient атрибута в метаданные, необходимо также указать аннотацию @MetaProperty.

@Version

Указывает, что данное поле хранит версию для поддержки оптимистичной блокировки сущностей.

Применение такого поля необходимо при реализации классом сущности интерфейса Versioned (базовый класс StandardEntity уже содержит такое поле).

Пример:

@Version
@Column(name = "VERSION")
private Integer version;