Статьи

Использование представлений базы данных в Grails

Этот пост является кратким объяснением того, как использовать представления базы данных в Grails.

Для введения я попытался обобщить, что такое представления базы данных. Однако я заметил, что не могу описать это лучше, чем это уже сделано в Википедии. Поэтому я просто процитирую сводку View (SQL) из Википедии здесь:

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

(Википедия)

пример

Предположим, у нас есть приложение Grails со следующими классами домена:

1
2
3
4
5
class User {
  String name
  Address address
  ...
}
1
2
3
4
class Address {
  String country
  ...
}

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

Создание вида

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

Чтобы создать представление, нам просто нужно создать новый набор изменений:

1
2
3
4
5
6
7
changeSet(author: '..', id: '..') {
  createView("""
      SELECT u.id, u.name, a.country
      FROM user u
      JOIN address a on u.address_id = a.id
    """, viewName: 'user_with_country')
}

Здесь мы создаем представление с именем user_with_country, которое содержит три значения: идентификатор пользователя, имя пользователя и страну.

Создание класса домена

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

1
2
3
4
5
6
7
8
9
class UserWithCountry {
  String name
  String country
 
  static mapping = {
    table 'user_with_country'
    version false
  }
}

Обратите внимание, что мы отключаем управление версиями, задав для параметра version значение false (в нашем представлении нет столбца версии).

На данный момент мы просто должны быть уверены, что наш набор изменений базы данных выполняется до того, как hibernate попытается создать / обновить таблицы при запуске приложения. Обычно это можно сделать, отключив создание таблицы hibernate в DataSource.groovy и включив автоматическую миграцию при запуске приложения, установив для grails.plugin.databasemigration.updateOnStart значение
правда. В качестве альтернативы это может быть достигнуто путем ручного выполнения всех новых наборов изменений с помощью команды dbm-update .

использование

Теперь мы можем использовать наш класс UserWithCountry для доступа к представлению:

1
2
3
4
5
6
7
8
9
Address johnsAddress = new Address(country: 'england')
User john = new User(name: 'john', address: johnsAddress)
john.save(failOnError: true)
 
assert UserWithCountry.count() == 1
 
UserWithCountry johnFromEngland = UserWithCountry.get(john.id)
assert johnFromEngland.name == 'john'
assert johnFromEngland.country == 'england'

Преимущества просмотров

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