5. Взаимодействие с базой данных

Объектные запросы

Кроссплатформенные запросы, которые выполняются на уровне объектов класса.

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

Пример запроса

new OQuery(Bs_GoodsAta.Type) {  
  where(t.sSystemName === spMnemoCode)  
}

Методы

  • where
    Условие запроса.

  • orderBy
    Выражение для сортировки резуьтата

  • batchAll
    Массовая загрузка объектов. Возвращает строки с прогруженными записями всех коллекций этого класса.

  • forUpdate
    Выполнение запроса с блокированием вернувшихся записей

  • forUpdateNoWait
    Выполнение запроса с блокирование вернувшихся записей, без ожидания разблокирования, если записи уже заблокированы другой сессией.

  • tryCacheQueryResults
    Попытаться закешировать результат запроса. Смотри пункт «Кеширование»

  • unique
    Говорит, что запрос возвращает одну уникальную запись. Позволяет использовать cache-index’ы, указанные в orm класса

Кеширование объектных запросов

Кеширование запросов работает только для классов с разделяемым режимом кеширования(Shared).

Кэширование по полю

Кеширование через cache-index’ы указанные в orm класса. Такой запрос должен возвращать одну строку и дополняется командой unique(). Например для атрибутов мнемокода класса в orm формируется запись:

<cache-index>  
  <column-name>SSYSTEMNAME</column-name>  
</cache-index>

Запрос выглядит следующим образом:

new OQuery(entityAta.Type) {  
  unique()  
  where(t.sSystemName*=== spMnemoCode)  
}
Кэширование объектных запросов

Кэширование объектных запросов возможно по требованию в случае, если класс настроен для сохранения в разделяемом кэше.

Чтобы включить кэширование запроса:

  • Добавьте в запрос опцию tryCacheQueryResults().
    Результат такого запроса будет кэширован, если транзакция не находится в режиме редактирования разделяемых объектов.

Пример запроса:

new OQuery(entityAta.Type) {  
  tryCacheQueryResults ()  
  where(t.sSystemName === spMnemoCode)  
}

Транзакционный индекс

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

Пример объявления:

lazy val idxidParent = TxIndex(Btk_GroupAta.Type)(_.idParentGroup)

Методы

  • byKey
    Посетитель по ключу индекса.

  • refreshByKey
    Посетитель по ключу индекса c обновлением из базы данных.

  • queryKeys
    Кеширование ключей индекса.

  • forPartition
    Открывает секцию для массового обновления индекса. Используется для прозрачного массового обновления после очистки транзакционного кэша. Секции могут быть вложенными друг в друга, в таком случае ключи суммируются.

byParent

Метод есть у классов коллекций, возвращает обходчик записей отфильтрованных по идентификатору предка

Реляционные запросы

Для обработки реляционных запросов в основном используется методы на базе anorm.

Для более удобного использования в контекст бизнес логики добавлены дополнительные функции.

ASQL

Выполнение запроса на чтение Создаёт объект AnormSql для выполнения запроса к базе без модификации данных. Если в текущей сессии начата транзакция, SQL-выражение выполняется в ней. Если транзакция в сессии не начата, запрос выполнится в автономной sql-транзакции.

Пример:

val idTrigger = 1
ASQL"SELECT t.sCaption as sHeadline FROM Btk_JobSchedule t WHERE t.id = $idTrigger".as(nStr("sHeadline").*).headOption

ATSQL

Выполнение запроса с изменением данных или блокировками Создаёт объект AnormSql с возможностью модификации данных. Если в текущей сессии начата транзакция, SQL-выражение выполняется в ней. Если в текущей сессии транзакция не начата, она будет начата.

Пример:

ATSQL("alter table bs_barcode add id int8;").execute()

ASelect

Выполнение запросов на чтение\запись с большим количеством колонок.

Пример:

for (rv <- new ASelect {
  val nParentLevel = asInt("nParentLevel")
  val gidParent = asString("gidParent")
  val gidChild = asString("gidChild")
  val idParent = asLong("idParent")
  SQL"""
  select nParentLevel,gidParent,gidChild,idParent,idChild from table
  """
}) {
  println(rv.nParentLevel())
  //запрос поля без его предварительного объявления
  println(rv.get("idChild").asNLong())
}