Option-поля

Довольно часто в реляционных базах для бизнес-приложений необходимо иметь дело со случаем, когда какое-либо поле может принимать лишь несколько значений из фиксированного списка. Например, может оказаться так, что поле "state" в вашей таблице может принимать лишь значения "new, processing, finished, error", и никакие иные.

Т. к. список фиксированный, делать отдельный справочник и внешний ключ при этом не представляется разумным. Более того, для оптимизации объёма таблицы и скорости обработки, часто имеет смысл применять целочисленные поля, присваивая определённый "смысл" целочисленным значениям, например, так:

  • 0 - new

  • 1 - processing

  • 2 - finished

  • 3 - error

Celesta поддерживает упрощённую работу с такими полями.

Чтобы объявить, что поле может принимать лишь значения из определённого списка, необходимо прописать свойство option в CelestaDoc целочисленного или текстового поля. Например, так:

create table foo
  ...
  /**целочисленное поле статуса
  {option: [new, processing, finished, error]}*/
  state int,
  /**текстовое поле статуса
  {option: [created, closed]*/
  state2 varchar(6)

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

Например, для нашей таблицы foo будут автоматически созданы два вложенных класса в классе fooCursor:

public static final class State {
    public static final Integer new = 0;
    public static final Integer processing = 1;
    public static final Integer finished = 2;
    public static final Integer error = 3;
    private State() {}
}
public static final class State2 {
    public static final String created = "created";
    public static final String closed = "closed";
    private State() {}
}

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

FooCursor foo = new FooCursor(context)
foo.setRange(foo.COLUMNS.state(), FooCursor.State.finished)
if (FooCursor.State2.closed.equals(foo.getState2()){
    ....
}