Работа с Grails: GORM - Забавное название и серьезная технология

Работа с базами данных в Grails

Любой хороший каркас для разработки Web-приложений требует основательной стратегии для сохранения объектов (persistence). В этой второй статье серии Работа с Grails Скотт Дэвис знакомит с GORM (Grails Object Relational Mapping - расширение Grails для объектно-реляционного преобразования). В статье показывается, насколько просто с его помощью создавать отношения между таблицами, подключать правила для проверки данных и изменять реляционные базы данных в Grails-приложениях.

Скотт Дэвис, главный редактор, AboutGroovy.com

Скотт Дэвис (Scott Davis) является международно признанным автором, лектором и разработчиком программного обеспечения. Среди его книг: Groovy Recipes: Greasing the Wheels of Java, GIS for Web Developers: Adding Where to Your Application, The Google Maps API и JBoss At Work.



25.11.2009

В прошлом месяце вводная статья серии Работа с Grails познакомила с новым каркасом для разработки Web-приложений, называемым Grails. Grails включает в себя такие современные подходы, как MVC (Model-View-Controller - модель-представление-контроллер), разделение обязанностей (separation of concerns) и соглашение по конфигурации (convention over configuration). В сочетании со встроенными возможностями скаффолдинга Grails позволяет получить первую работающую версию Web-сайта за несколько минут.

Эта статья посвящена другой области, которую также упрощает Grails: долговременному сохранению объектов с помощью API GORM. Статья начинается с описания того, что такое ORM (object-relational mapper - объектно-реляционный преобразователь) и как создать отношение типа "один ко многим". Далее рассказывается о проверке данных, гарантирующей, что приложение не будет поражено синдромом garbage in/garbage out (неправильные данные на входе/неправильные данные на выходе). Будет показано практическое использование Grails ORM DSL (domain-specific language - язык для конкретной доменной области), который позволяет детально настраивать способ постоянного сохранения POGO-объектов (plain old Groovy objects - обычные старые Groovy-объекты) за рамками приложения. Наконец, будет показано, как легко переключиться с одной реляционной базы данных на другую. Подойдет любая база данных, поддерживающая JDBC-драйвер и Hibernate-диалект.

Об этой серии статей

Grails - это современный каркас для разработки Web-приложений, соединяющий известные Java-технологии, например, Spring и Hibernate с современными подходами типа "соглашение по конфигурации" (convention over configuration). Будучи написан на Groovy, Grails обеспечивает прозрачную интеграцию с существующим Java-кодом, одновременно добавляя гибкость и динамику языков сценариев. После изучения Grails ваши взгляды на Web-разработку изменятся навсегда.

Определение ORM

Реляционные базы известны с конца 70-х годов, а разработчикам ПО до сих пор приходится тратить силы на то, чтобы эффективно сохранять в них объекты и загружать обратно. Современное ПО основано на объектно-ориентированных принципах, а не на реляционном подходе, используемом в большинстве популярных баз данных.

Образовался целый класс программ - ORM (объектно-реляционный преобразователь) - для облегчения задачи перемещения данных между базами данных и кодом и обратно. В частности, эту проблему пытаются решить три популярных Java API - Hibernate, TopLink и JPA (Java Persistence API - Java API для перманентного хранения объектов) (см. раздел Ресурсы), хотя ни один из них не является идеальным. Эта проблема настолько постоянна (случайный каламбур), что у нее даже есть собственное название: object-relational impedance mismatch (объектно-реляционное рассогласование) (см. раздел Ресурсы).

GORM - это "тонкий" Groovy-фасад над Hibernate. (По-видимому, "Gibernate" показалось создателям не таким благозвучным, как "GORM"). Это значит, что все существующие для Hibernate приемы работают и здесь; например, полностью поддерживаются HBM-файлы для преобразования и аннотирования. Однако эта статья фокусируется на интересных новых возможностях, которые привносит GORM.

Объектно-ориентированные базы данных и Grails

Некоторые разработчики пытаются устранить проблему "объектно-реляционного рассогласования", используя базы данных, поддерживающие объекты естественным способом. Серия статей The busy Java developer's guide to db4o Теда Ньюарда (Ted Neward) на страницах developerWorks хорошо освещает этот предмет, показывая современные объектно-ориентированные базы на практике. Было бы здорово, если бы какой-нибудь J2EE-программист написал db4o-плагин для Grails, доказав, что объектно-ориентированные базы данных так же готовы к профессиональному использованию, как и их реляционные аналоги. Однако пока использование GORM и традиционной реляционной базы данных - это лучшая стратегия для перманентного хранения объектов в Grails.

Создание связей "один-ко-многим"

Сохранение POGO-объектов в таблицы базы данных на первый взгляд кажется не такой уж сложной задачей. Действительно если один POGO-объект отображается на одну таблицу, в этом нет ничего сложного, свойства POGO-объекта идеально совпадают со столбцами таблицы. Но если объектная модель сколько-нибудь сложна, например, содержит два POGO-объекта, связанных между собой, задача может резко усложниться.

Например, рассмотрим Web-сайт приложения Trip Planner, разработка которого была начата в прошлой статье. Неудивительно, что POGO-объект Trip играет важную роль в приложении. Откройте файл Open grails-app/domain/Trip.groovy (см. листинг 1) в текстовом редакторе:

Листинг 1. Класс Trip
class Trip { 
  String name
  String city
  Date startDate
  Date endDate
  String purpose
  String notes
}

Каждый из атрибутов в листинге 1 легко и просто отображается в соответствующее поле в таблице Trip. Напомню из предыдущей статьи, что все POGO-классы, хранящиеся в каталоге grails-app/domain, получают соответствующую таблицу, которая автоматически создается при запуске Grails. По умолчанию Grails использует встроенную базу данных HSQLDB, но к концу этой статьи будет показано, как можно использовать любую удобную базу данных.

Путешествие часто включает в себя перелет, так что имеет также создать класс Airline (см. листинг 2):

Листинг 2. Класс Airline
class Airline { 
  String name
  String url
  String frequentFlyer
  String notes
}

Теперь необходимо связать эти два класса. Планирование поездки в Чикаго с помощью авиакомпании XYZ представляется в Groovy точно так же, как и в Java-коде - путем добавления свойства Airline в класс Trip (см. листинг 3). Этот прием называется композицией объектов (object composition) (см. раздел Ресурсы).

Листинг 3. Добавление свойства Airline к классу Trip
class Trip { 
  String name
  String city
  ...
  Airline airline
}

Все это просто и хорошо выглядит в модели ПО, но в реляционных базах данных применяется несколько другой подход. Каждая запись в таблице имеет уникальный идентификатор (unique ID), называемый первичным ключом (primary key). Добавление поля airline_id в таблицу Trip позволяет привязать одну запись к другой (в данном случае запись "авиакомпания XYZ" к записи "поездка в Чикаго"). Это называется связью "один ко многим" (one-to-many relationship): с одной авиакомпанией может быть связано много поездок. Примеры связей "один-к-одному" и "многие-ко-многим" можно найти в онлайновой документации Grails (см. раздел Ресурсы).

У представленной здесь схемы базы данных есть одна проблема. Возможно, база данных уже была успешно нормализована (normalized) (см. раздел Ресурсы), но теперь столбцы в таблице не синхронизированы с моделью ПО. Если заменить поле Airline на поле AirlineId, получится, что детали реализации (тот факт, что POGO-объекты перманентно хранятся в базе данных) просачиваются в объектную модель. Джоел Спольски (Joel Spolsky) назвал это "законом протекающих абстракций" (Law of Leaky Abstractions) (см. раздел Ресурсы).

GORM помогает решить проблему протекающих абстракций, позволяя представить объектную модель тем способом, который используется в Groovy. Он решает задачи реляционного представления в "фоновом" режиме, но, как будет показано далее, его настройки по умолчанию можно легко переопределить. GORM - это не "непрозрачный" (opaque) уровень абстракции, скрывающий подробности реализации базы данных, а представляет собой "полупрозрачный" (translucent) слой: он пытается сам сделать так, чтобы все заработало, но если функциональность необходимо настроить, он не будет препятствовать пользователю. Это открывает пользователю лучшие возможности обоих решений.

Свойство Airline уже было добавлено в POGO-класс Trip. Чтобы завершить создание связи "один-ко-многим", необходимо добавить параметр настройки hasMany к POGO-классу Airline, как показано в листинге 4:

Листинг 4. Создание связи "один-ко-многим" в классе Airline
class Airline { 
  static hasMany = [trip:Trip]

  String name
  String url
  String frequentFlyer
  String notes
}

Статический параметр hasMany - это Groovy-коллекция типа HashMap; ключом является trip, а значением, хранящимся по этому ключу, - класс Trip. Если требуется добавить дополнительные связи "один-ко-многим" в класс Airline, необходимо поместить в квадратные скобки список пар ключ/значение, разделенных запятыми.

Каскадное удаление

То, как модель выглядит сейчас, может привести к появлению "осиротевших" записей в базе данных: при удалении авиакомпаний из таблицы Airline в таблице Trip могут появиться записи, указывающие на несуществующего родителя. Чтобы избежать подобного сценария, можно добавить соответствующую статическую коллекцию belongsTo типа HashMap в класс, находящейся на стороне "-ко-многим".

Теперь создайте простой класс AirlineController (см. листинг 5) в каталоге grails-app/controllers, чтобы можно было увидеть новую связь "один-ко-многим" в работе:

Листинг 5. Класс AirlineController
class AirlineController { 
  def scaffold = Airline
}

Напомню из прошлой статьи, что код def scaffold указывает Grails динамически создать основные методы list(), save() и edit() во время исполнения. Он также указывает Grails динамически создать представления на основе GSP-страниц (GroovyServer Page - серверные страницы Groovy). Необходимо убедиться, что оба класса TripController и AirlineController содержат def scaffold. Если в подкаталогах trip или airline каталога grails-app/views остались какие-нибудь GSP-страницы, например, после ввода команды grails generate-all, то их надо удалить. В нашем примере необходимо гарантировать, что Grails сможет динамически построить контроллеры и представления.

Теперь, когда классы предметной области и контроллеры готовы, можно запустить Grails. Необходимо ввести команду grails prod run-app для запуска приложения в рабочем режиме. Если все пройдет успешно, будет выведено приветственное сообщение со следующим текстом:

Server running. Browse to http://localhost:8080/trip-planner

Как избежать ошибок с конфликтом портов

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

В Web-браузере должны быть показаны ссылки для AirlineController и TripController. Далее следует нажать ссылку AirlineController и заполнить форму с информацией об авиакомпаниях XYZ, как показано на рисунке 1:

Рисунок 1. Связь "один-ко-многим": сторона "один"
Рисунок 1. Связь один-ко-многим: сторона один

Не стоит переживать, если сортировка полей в алфавитном порядке вам не подходит. В следующем разделе будет показано, как переопределить ее.

Теперь необходимо создать новую поездку, как показано на рисунке 2. Отметим, что появился список с объектами Airline. Каждая запись, добавленная в таблицу Airline, присутствует в этом списке. Не стоит беспокоиться о "просачивании" первичного ключа - в следующем разделе будет показано, как добавить наглядное описание.

Рисунок 2. Связь "один ко многим": сторона "ко многим"
Рисунок 2. Связь один ко многим: сторона ко многим

Шаблон naked objects

Только что было показано, как добавление указания (статическое поле hasMany) в POGO-класс Airline влияет сразу и на таблицу, создаваемую в фоновом режиме, и на представление, которое генерируется для пользователя. Этот шаблон naked objects (открытые объекты) (см. раздел Ресурсы) интенсивно используется в Grails для декорирования объектов предметной области. При добавлении этой информации напрямую в POGO-класс исчезает необходимость во внешних конфигурационных XML файлах. Наличие всей информации в одном месте положительно сказывается на продуктивности.

Например, для избавления от "просочившегося" первичного ключа, который показывается в выпадающем списке, можно просто добавить метод toString в класс Airline, как показано в листинге 6:

Листинг 6. Добавление метода toString к классу Airline
class Airline { 
  static hasMany = [trip:Trip]

  String name
  String url
  String frequentFlyer
  String notes
    
  String toString(){
    return name
  }
}

С этого момента в качестве значения, отображаемого в выпадающем списке, используется название авиакомпании. Однако самый привлекательный аспект состоит в том, что если Grails уже запущен и работает, то все, что необходимо, чтобы изменения вступили в силу - это сохранить класс Airline.groovy. Создайте в Web-браузере новый объект Trip, чтобы увидеть это на практике. Так как представления генерируются динамически, можно быстро переключаться между текстовым редактором и Web-браузером до тех пор, пока не будет получено требуемое представление, и при этом не требуется перезагрузка сервера.

Теперь необходимо исправить проблему с сортировкой полей по алфавиту. Для этого необходимо внести еще одно конфигурационное изменение в POGO-класс: блок static constraints. Добавьте в этот блок поля в порядке, показанном в листинге 7. (Эти ограничения не влияют на порядок столбцов в таблице - только на представление.)

Листинг 7. Изменение порядка сортировки полей в классе Airline
class Airline { 
  static constraints = {
    name()
    url()
    frequentFlyer()
    notes()  
  }

  static hasMany = [trip:Trip]
    
  String name
  String url
  String frequentFlyer
  String notes
  
  String toString(){
    return name
  }
}

Сохраните эти изменения в файле Airline.groovy и создайте в Web-браузере новую авиакомпанию. Теперь поля должны отобразиться в порядке, определенном в листинге 7, как показано на рисунке 3:

Рисунок 3. Измененный порядок полей
Рисунок 3. Измененный порядок полей

Прежде чем читатель обвинят меня в нарушении DRY-принципа (Don't Repeat Yourself - не повторяться) (см. раздел Ресурсы) из-за ненужного повторного ввода названий полей в POGO-классе, хочу уверить, что есть важная причина поместить их в отдельный блок. Эти круглые скобки в блоке static constraints в листинг 7 недолго будут оставаться пустыми.


Проверка данных

В добавление к установлению порядка полей блок static constraints также позволяет установить определенные правила для проверки правильности данных (validation rules). Например, можно установить ограничение по длине для полей типа String (по умолчанию они могут быть длиной до 255 символов). Можно проверить, что значения типа String соответствуют определенному шаблону (например, адресу электронной почты или URL). Также можно сделать поля обязательными или необязательными. Полный список возможных правил проверки приведен в онлайновой документации Grails (см. Ресурсы).

В листинге 8 приведен класс Airline с правилами для проверки данных, помещенными в блок с ограничениями:

Листинг 8. Добавление проверок данных к классу Airline
class Airline { 
  static constraints = {
    name(blank:false, maxSize:100)
    url(url:true)
    frequentFlyer(blank:true)
    notes(maxSize:1500)  
  }

  static hasMany = [trip:Trip]
    
  String name
  String url
  String frequentFlyer
  String notes

  String toString(){
    return name
  }
}

Снова сохраните измененный файл Airline.groovy и создайте в Web-браузере новую авиакомпанию. Если нарушить правила проверки, будет показано сообщение с предупреждением, как на рисунке 4:

Рисунок 4. Сообщения с предупреждениями о нарушении правил проверки
Рисунок 4. Сообщения с предупреждениями о нарушении правил проверки

Можно настроить сообщения с предупреждениями в файле messages.properties в каталоге grails-app/i18n. Отметим, что сообщения с предупреждениями по умолчанию локализованы на нескольких языках. (См. раздел о проверки в online-документации Grails с подробной информацией о том, как создавать специальные сообщения для отдельных классов или отдельных полей.)

Большая часть ограничений в листинге 8 влияет только на уровень представления, но некоторые влияют также на уровень постоянного хранения данных. Например, столбец name в базе данных теперь имеет длину в 100 символов. Поле notes, помимо трансформации из поля ввода (input field) в текстовую область (text area) в представлении (это происходит для полей с длиной больше 255 символов), превратилось из столбца типа VARCHAR в столбец типа TEXT, CLOB или BLOB соответственно. Это зависит от типа базы данных, используемой в фоновом режиме, и ее Hibernate-диалекта, которые можно переопределить, что к этому моменту уже не должно вызывать удивления.


Язык предметной области: Grails ORM DSL

Можно переопределить настройки Hibernate по умолчанию, используя любой из его обычных методов конфигурирования: HBM-файлы для преобразования или аннотации. Но Grails предоставляет и третий способ, следующий стилю шаблона naked-objects. Достаточно просто добавить блок static mapping в POGO-класс, чтобы переопределить названия по умолчанию для таблицы и столбцов, как показано в листинге 9:

Листинг 9. Использование GORM DSL
class Airline { 
  static mapping = {
    table 'some_other_table_name'
    columns {
      name column:'airline_name'
      url column:'link'
      frequentFlyer column:'ff_id'
    }
  }

  static constraints = {
    name(blank:false, maxSize:100)
    url(url:true)
    frequentFlyer(blank:true)
    notes(maxSize:1500)  
  }

  static hasMany = [trip:Trip]
    
  String name
  String url
  String frequentFlyer
  String notes

  String toString(){
    return name
  }
}

Блок mapping особенно полезен, если имеются существующие таблицы, которые необходимо использовать в новом Grails-приложении. Хотя в данной статье затрагиваются только основы, возможности ORM DSL гораздо шире простого переопределения названий таблиц и столбцов. Можно переопределить тип данных по умолчанию для каждого из столбцов. Можно настроить стратегию генерации первичных ключей или даже определить составной первичный ключ. Можно изменить настройки кэша Hibernate, настроить поля, используемые в связях для внешних ключей и многое другое.

Важная вещь, которую стоит напомнить: это что все эти настройки сосредоточены в одном месте: POGO-классе.


Знакомство с файлом DataSource.groovy

Все, что мы делали до сих пор, касалось настройки индивидуальных классов. Теперь пришло время сделать шаг назад и внести некоторые глобальные изменения. Параметры конфигурации, относящиеся к базе данных и общие для всех классов предметной области, хранятся в общем файле grails-app/conf/DataSource.groovy, показанном в листинге 10. Откройте этот файл в текстовом редакторе и изучите его:

Листинг 10. Файл DataSource.groovy
dataSource {
  pooled = false
  driverClassName = "org.hsqldb.jdbcDriver"
  username = "sa"
  password = ""
}
hibernate {
  cache.use_second_level_cache=true
  cache.use_query_cache=true
  cache.provider_class='org.hibernate.cache.EhCacheProvider'
}
// environment specific settings
environments {
  development {
    dataSource {
      dbCreate = "create-drop" // one of 'create', 'create-drop','update'
      url = "jdbc:hsqldb:mem:devDB"
    }
  }
  test {
    dataSource {
      dbCreate = "update"
      url = "jdbc:hsqldb:mem:testDb"
    }
  }
  production {
    dataSource {
      dbCreate = "update"
      url = "jdbc:hsqldb:file:prodDb;shutdown=true"
    }
  }
}

В блоке dataSource (источник данных) можно изменить параметры: driverClassName (класс драйвера), username (имя пользователя) и password (пароль), используемые для подключения к базе данных. Блок hibernate позволяет настроить параметры кэша (если вы не являетесь экспертом в Hibernate, эти параметры лучше не трогать). Но по-настоящему интересные вещи происходят в блоке environments (среда).

Напомню из прошлой статьи, что Grails может работать в трех режимах: development (разработка), test (тестирование) и production (рабочий режим). Когда вводится команда grails prod run-app, это указывает Grails использовать настройки базы данных из блока production. Если необходимо настроить значения username и password в зависимости от типа среды, достаточно просто скопировать эти настройки из блока dataSource в конкретный блок environments и изменить их значения. Настройки в блоке environments переопределяют значения в блоке dataSource.

Параметр настройки url - это строка подключения JDBC. Стоит отметить, что в режиме production HSQLDB использует хранилище на основе файла, а в режимах development и test HSQLDB - хранилище данных, располагающееся прямо в памяти. В прошлом месяце говорилось, что надо запускать приложение в режиме production, если необходимо, чтобы записи в таблице Trip сохранялись при перезапусках сервера. Теперь становится понятно, как добиться такого же результата в режимах development и test - просто скопировать параметр настройки url из блока production. Конечно, переключение Grails на DB2, MySQL или другую традиционную базу данных на основе файлов также решит проблему исчезающих записей (disappearing records). (Настройки для DB2 и MySQL будут показаны чуть дальше).

Значение параметра dbCreate также задает поведение в разных средах. Это псевдоним для базовой настройки hibernate.hbm2ddl.auto, которая определяет, как Hibernate управляет таблицами за рамками приложения. Если значение dbCreate равно create-drop, это говорит о том, что Hibernate создает (create) таблицы при запуске и уничтожает (drop) их при выключении сервера. Если сделать это значение равным create, то Hibernate при необходимости создаст новые таблицы и модифицирует существующие, но все записи из таблиц будут удаляться в промежутках между запусками сервера. Значение по умолчанию для режима production - update указывает сохранять все данные между запусками сервера, одновременно при необходимости создавая или изменяя таблицы.

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

Также просто добавить свою собственную среду. Предположим, что в компании имеется практика выпуска бета-версий. Достаточно просто создать блок beta в файле DataSource.groovy вслед за другими блоками. (Также можно добавить блок environments в файл grails-app/conf/Config.groovy для настроек, которые не относятся к базе данных). После этого для запуска Grails в бета-режиме достаточно ввести grails -Dgrails.env=beta run-app.


Смена используемой базы данных

Если Hibernate разрешено управлять таблицами через параметр настройки dbCreate, то заставить Grails работать с новой базой данных можно в три простых шага: создать базу данных и учетную запись в ней, скопировать JDBC-драйвер в каталог lib и исправить настройки в файле DataSource.groovy.

Инструкции по созданию базы данных и пользователей могут значительно различаться для разных продуктов. Для DB2 существует пошаговое руководство, которое можно изучать в онлайновом режиме (см. раздел Ресурсы). После того как база данных и пользователь созданы, необходимо настроить файл DataSource.groovy, чтобы указав в нем значения из листинга 11. (Показанные значения подразумевают, что база данных называется trip).

Листинг 11. Настройки DB2 для файла DataSource.groovy
  driverClassName = "com.ibm.db2.jcc.DB2Driver"
  username = "db2admin"
  password = "db2admin"
  url = "jdbc:db2://localhost:50000/trip"

Если уже имеется установленная версия MySQL, можно выполнить шаги, приведенные в листинге 12, чтобы войти в базу данных как пользователь root и создать базу данных trip:

Листинг 12. Создание базы данных MySQL
$ mysql --user=root
mysql> create database trip;
mysql> use trip;
mysql> grant all on trip.* to grails@localhost identified by 'server';
mysql> flush privileges;
mysql> exit
$ mysql --user=grails -p --database=trip

После того как база данных и пользователь созданы, необходимо изменить файл DataSource.groovy, указав значения, приведенные в листинге 13:

Листинг 13. Настройки MySQL для файла DataSource.groovy
  driverClassName = "com.mysql.jdbc.Driver"
  username = "grails"
  password = "server"
  url = "jdbc:mysql://localhost:3306/trip?autoreconnect=true"

После создания базы данных, копирования JAR-файла с JDBC-драйвером в каталог lib и изменения значения в файле DataSource.groovy введите еще раз команду grails run-app. Теперь Grails работает с указанной базой данных, а не HSQLDB.


Заключение

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

Следующая статья этой серии будет посвящена Web-уровню. В ней будет представлена дополнительная информация о GSP-страницах и различных библиотеках тегов Groovy (Groovy TagLibs). Будет показано, как разбивать GSP-страницы на части (partials) - фрагменты разметки, которые можно использовать на нескольких страницах. И, наконец, будет показано, как персонифицировать стандартные шаблоны, использующиеся в автоматически генерируемых (scaffolded) представлениях.

Пока же - удачной работы с Grails.

Ресурсы

Научиться

  • Mastering Grails: GORM: Funny name, serious technology: оригинал статьи (EN).
  • Mastering Grails : другие статьи из этой серии с подробной информацией о Grails и возможностях его применения.
  • Grails: Web-сайт, посвященный Grails.
  • Grails Framework Reference Documentation (EN): "библия" Grails.
  • Groovy Recipes (EN) (Pragmatic Bookshelf, март 2008 г.): узнайте подробнее о Groovy и Grails в последней книге Скотта Дэвиса.
  • Hibernate, TopLink, и JPA: популярные Java API для объектно-реляционного преобразования.
  • Object-relational impedance mismatch (EN): проблемы, возникающие в ходе объектно-реляционного преобразования.
  • Object composition (EN): шаблон проектирования для объединения простых объектов в более сложные.
  • Database normalization (EN): подход к проектированию таблиц реляционных баз данных, помогающий избежать аномалий в данных.
  • Leaky abstraction (EN): "антишаблон" проектирования, в котором, согласно Джоелу Спольски (Joel Spolsky), "все нетривиальные абстракции в определенной степени "протекают""
  • Naked objects (EN): архитектурный шаблон проектирования по созданию объектов предметной области.
  • DRY (EN): концептуальный подход, главной идеей которого является отсутствие дублирования информации.
  • Hello World: Learn the basic features and concepts of DB2 for Linux, UNIX, and Windows (EN) (developerWorks, декабрь 2006 г.): простое учебное пособие с обзором DB2 для ОС Linux, UNIX и Windows, включающее демонстрации и упражнения начального уровня.
  • Practically Groovy : серия статей на страницах developerWorks, в которой исследуется практическое использование Groovy и области его применения.
  • Groovy: Web-сайт проекта Groovy с дополнительной информацией.
  • AboutGroovy.com (EN): Web-сайт с последними новостями и ссылками на статьи о Groovy.
  • Model-View-Controller (EN): популярный шаблон проектирования, используемый в Grails.
  • Safari bookstore: сайт магазина книг по ИТ.(EN)
  • Раздел Технология Java сайта developerWorks: сотни статей обо всех аспектах Java-программирования.

Получить продукты и технологии

  • DB2: скачать ознакомительную версию СУБД DB2 9.5.
  • Grails: скачать последнюю версию Grails.(EN)
  • Скачайте ознакомительные версии продуктов IBM и опробуйте на практике средства для разработки приложений и связующее программное обеспечение DB2®, Lotus®, Rational®, Tivoli® и WebSphere.(EN)

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Технология Java, Open source
ArticleID=449712
ArticleTitle=Работа с Grails: GORM - Забавное название и серьезная технология
publish-date=11252009