Зрелость J2EE

6yrop

Удивляет, что в технологии, которой уже не один год, и которая позиционируется как платформа для создания мегасложных бизне-приложений, есть вот такой косяк. В языке запросов (речь идет Query Language, который описан в спецификации J2EE, и который очень близок к HibernateQL) нельзя использовать подзапросы во FROM-е. Там есть сноска, в которой говориться, что подзапросы во FROM-е будут рассмотрены в следующих релизах. Но вряд ли у них получиться сделать это просто, если не делать точную кальку с SQL .
В реляционной теории свойство замкнутости -- результат запроса можно использовать в качестве аргумента другого запроса -- является основным свойством реляционной алгебры, и SQL поддерживает это свойство.


Unlike many other persistence solutions, Hibernate does not hide the power of SQL from you and guarantees that your investment in relational technology and knowledge is as valid as always.

Вообще странно все это, Hibernate, а следом за ним и J2EE, закрывают нам прелести реляционной модели и SQL-я. Но зачем?

psm-home

А они не закрывают. Если ты внимательно почитаешь что-нибудь хорошее и правильное про Hibernate, например Hibernate in Action, то ты прочтешь там, что создатели Hibernate вовсе не позиционируют его как "средство от всех болезней". SQL никто не отменял. Hibernate имеет вполне определенную нишу. Это OR mapper. Средство для отображения графа объектов на таблицы реляционнной СУБД. Это не означает, что все надо делать с его помощью. Запросы для генерации отчетов например, не стоит писать на HQL. В общем, косяка нет. Что касается цитаты, то в ней имеется в виду, что ты можешь через Hibernate исполнять свои драгоценные SQL запросы, а он позаботится о преобразовании ResultSet в объекты.

6yrop

1. Я говорил не о Hibernate, а о Java Platform, Enterprise Edition, т.е. спецификации для создания приложения масштаба предприятия. А получается, что там описаны только куски архитектуры? т.е. они не могут предложить полную архитектуры и навязывают нам куски своих незаконченных мыслей?
2. Если можно пользоваться SQL, то сложно будет следить за переносимостью на другую СУБД. Кто будет следить (да и как что один из разработчиков не напишет SQL специфичный для конкретной СУБД? А люди часто ведутся на то, что при использовании Hibernate, приложение будет переносимо.
"средство от всех болезней"

если есть механизмы, которые дублируют друг друга, это всегда плохо. Архитектура должна освобождать программиста от технических деталей, у него не должно быть выбора -- на осмысленный выбор всегда тратиться время.
В общем, косяка нет. Что касается цитаты, то в ней имеется в виду, что ты можешь через Hibernate исполнять свои драгоценные SQL запросы, а он позаботится о преобразовании ResultSet в объекты.

присвоить п переменным значения, да это офигенно сложная задача

6yrop

Средство для отображения графа объектов на таблицы реляционнной СУБД.
Зачем это надо? тем более такое мострообразное как Hibernate?

Dasar

Чтобы уменьшить время, которое тратиться на кодирование этого отображения

6yrop

зачем отображение вообще нужно?

bastii

наверно люди хотят одновременно с одной стороны свои бизнес объекты, а с другой стороны функциональность датасетов

bastii

кстати, Hibenate как реализация OR под DLinq ой как подойдет

aleks058

Ты предметную область описываешь в ООП-языке, а данные хранить приходится (пока) в реляционном виде.
Ты можешь руками насоздавать классов и понопесать селектов, чтобы их заполнить данными, а также апдейтов, инсертов и делитов, чтобы сохранить изменения обратно в базу (этот муторный и неинтеллектуальный этап более-менее галимо делает студия 2005).
Либо ты можешь Hibernate попросить построить тебе набор классов с автоматически сгенеренными селектами и прочими командами для работы с базой и почти думать о том, как объекты сохранятся в базу.
И даже ходют слухи, что Hibernate умеет генерить скрипты для создания БД по иехархии классов.
И даже что-то умеет делать, чтобы адекватно реагировать на изменения объектной модели и/или структуры БД.

6yrop

инсерты, апдейты и делиты еще с Framework 1 генерит автоматически класс CommandBuilder .
Про селекты надо говорить по-подробнее, но там тоже у Hibernate спорные преимущества.

Hastya

Я вижу, Шурик, ты решил стать знаком Hibernate.
Это похвально.
Для начала почитай про Criteria API, Collections и Tuning Fetch Strategies.
Синхронизация со схемой БД в Hibernate имеется, есть такой ключик HBM2DDL_AUTO, поддерживающий несколько режимов, в том числе простейший create-drop.
"Прелести реляционной модели" это хорошо сказано, Hibernate как для того и был создан, чтобы эти прелести убрать подальше, и надо сказать, они достигли в этом больших успехов.
С DataSet-ами не знаком, но в Hibernate есть такая штука как Entity Mode, которая позволяет "дегидрировать" записи в dynamic maps или XML.

sergei1969

Либо ты можешь Hibernate попросить построить тебе набор классов с автоматически сгенеренными селектами и прочими командами для работы с базой и почти думать о том, как объекты сохранятся в базу.
Hibernate генерит select'ы на ходу
и не обязательно он будет генерить тебе классы, это делает Hibernate Tools. а так же реверс инжениринг базы или наоборот, создание ddl для базы по описаниям классов
Hibernate позволяет работать в проге чисто с твоими объектами, сохраняя их в неком хранилище и подгружая их оттуда

6yrop

для начала говоришь .
Читал я это всё, не впечатлило
Criteria API
В J2EE Criteria, кажется, вообще нет.
Collections
это к чему ты написал?

6yrop

Hibernate Tools
а там не требуется Tools for Hibernate Tools?

6yrop

Hibernate генерит select'ы на ходу
ага по HQL селекту генерит SQL селект. Очень за него рад, а может он еще и в шахматы умеет играть?

Hastya

Читал я это всё, не впечатлило
Тебя не впечатило, что твои любимые DataSets являются примерно 10% возможностей Hibernate?

6yrop

Тебя не впечатило, что твои любимые DataSets являются примерно 10% возможностей Hibernate?
по частям эти технологии вообще нельзя сравнивать. Они решают оду проблему, но по-разному, можно сравнивать только насколько успешно они ее решают.
Я не говорил, что DataSet-ы мне нравятся

Dasar

Ты когда-нибудь редактор данных, которые работают через dataset-ы писал?
тебе понравилось?

6yrop

редактор данных
а что это?

Dasar

программа для ввода и изменения структурированной информации

6yrop

да, в моих проектах были структурированные данные, и данные вводились и редактировались . Обертки над нетипизированными датасетами вполне сносно работали.

Dasar

> Обертки над нетипизированными датасетами вполне сносно работали.
На основе этого можно делать какие-то выводы?
Какое кол-во строчек кода у тебя приходилось на единицу функционала (например, на одно прикладное свойство)?

6yrop

Какое кол-во строчек кода у тебя приходилось на единицу функционала (например, на одно прикладное свойство)?
одна на get, одна на set. Я писал эти строчки вручную (в Hibernate строк все равно больше тогда был еще первый фремворк, сейчас есть partical классы, можно генерировать эти строчки простейшим генератором на основе схемы БД.

Dasar

для полей-ссылок, и полей- массивов тоже по одной строчке?

6yrop

да

Dasar

покажи, пожалуйста, эту одну строчку для свойства-коллекции (например, отношение 1<-> много с сильной связью, отношение много<->много со слабой связью)
ps
сильная связь требует удаления самих объектов, слабая - нет

6yrop


public IEntityCollection GetDivisions
{
return GetAdjacentEntities("Division");
}

Связь многие-ко-многим реляционная модель не поддерживает (соответственно DataSet-ы тоже). Я считаю, она и не нужна, без нее удается работать единообразно, и при этом сохраняя целостность данных, что нельзя сказать о подходе, который использует коллекции связанных сущностей внутри сущностей, в частности, в Hibernate (чтобы пояснить это могу привести пример).
Про сильную/слабую связь не понял, когда что удаляется?

Hastya

что нельзя сказать о подходе, который использует коллекции связанных сущностей внутри сущностей, в частности, в Hibernate (чтобы пояснить это могу привести пример).
Раз уж ты критикуешь Hibernate, то поясни. Того, что ты написал, очень мало. Я не вижу ни наследования, ни lazy-коллекций, ни кэширования, ни dirty checking, ни каскадности. Ту функциональность, которую ты перечисляешь, реализовывал еще 5-летней давности проект Turbine.

6yrop

По lazy-подгрузке у меня есть несколько вопросов.
1. Как я понимаю, она имеет смысл только в 2х-уровневой архитектуре, т.е. data access layer не может отдать объекты на другой уровень. Тогда зачем говорить о мегасложных, многофункциональных, масштабируемых приложениях, и упоминать J2EE?
2. Да и 2x-звенке это как-то странно выглядит
//получили экземпляр объекта Parent.
Parent parent = .....
//Отобразили его на пользовательском интерфейсе.
//Пользователь посмотрел на это. Попил чаю и нажал кнопку, которая вызвала вот такой код.
Transaction tx = null;
try {
    tx = sess.beginTransaction;
    Collection childs = parent.getChilds
    ...
    tx.commit;
}
catch (RuntimeException e) {
    if (tx != null) tx.rollback;
    throw e; // or display error message
}
Как написано в документации по Hibernate, транзакцию надо открывать всегда, когда требуется работа с базой. Интересно, что будет, если забыть открыть/закрыть транзакцию?
3. Каждый раз надо думать, как мы использует lazy-подгрузку. Если у нас много экземпляров parent-ов и у всех вызываем getChilds то lazy-подгрузку использовать нельзя, а в запросе надо указывать, что надо еще грузить child-ов. А если этих child-ов 6 типов? напряжено всех их указывать в каждом запросе. Я бы хотел иметь возможность создавать правило(а) подгрузки связанных сущностей, которое можно было бы использовать в нескольких запросах. Причем если за этим не уследить, то такие ошибки отлавливаются только при нагрузочном тестировании, которое требует дополнительных затрат.
Единственно, где lazy-подгрузка хорошо работает (с учетом пункта 3) это web-приложения (с точки зрения обмена данными фактически одноуровневые приложения).

6yrop

ни наследования
это сейчас лень обсужать
ни кэширования, ни dirty checking, ни каскадности.

в простой парадигме этого всего не нужно . Hibernate любит ставить сам себе задачи, а потом их решать

Hastya

1. Lazy-load это средство ограничить число запросов к базе прозрачным образом. Я не совсем понял, что почему это имеет смысл "только в 2х-уровневой архитектуре". У тебя есть какие-то проблемы с масштабируемостью Hibernate?
2. Hibernate разделяет понятия сессии (Unit of work) и транзакции. Я не понял, к какому варианту управления сессиями относится приведенный тобой кусок кода. Видимо, имеется в виду ручное управление транзакциями, а parent - detached?
Если у нас много экземпляров parent-ов и у всех вызываем getChilds то lazy-подгрузку использовать нельзя, а в запросе надо указывать, что надо еще грузить child-ов.

Не понял. Где это нужно указывать? в каком запросе? Ты просто вызываешь getChilds остальное за тебя делает Hibernate. Или вопрос по оптимизации SQL-кода, который генерирует Hibernate?

6yrop

Hibernate разделяет понятия сессии (Unit of work) и транзакции.
хибернейтовская сессия это не unit of work, это всего лишь одна из возможностей ее использования

A Session is an inexpensive, non-threadsafe object that should be used once, for a single request, a conversation, single unit of work, and then discarded.

6yrop

Я не понял, к какому варианту управления сессиями относится приведенный тобой кусок кода.
session-per-conversation
 
а parent - detached

нет. Если detached, еще надо делать attach

6yrop

Не понял. Где это нужно указывать? в каком запросе? Ты просто вызываешь getChilds остальное за тебя делает Hibernate. Или вопрос по оптимизации SQL-кода, который генерирует Hibernate?
Почитай вот здесь
http://www.hibernate.org/hib_docs/v3/reference/en/html/perfo...
Это так называемая проблема N+1 селектов.
Кстати, вот подтверждение, что lazy-подгрузка должна быть внутри транзакции
The fix is to move the code that reads from the collection to just before the transaction is committed.

6yrop

Я не совсем понял, что почему это имеет смысл "только в 2х-уровневой архитектуре".
потому что "Hibernate does not support lazy initialization for detached objects.". А как ты передашь не detached objects на другую машину?

6yrop

[offtopic]
Прикольно встретить в документации по Hibernate вот такую фразу
Please note that this is mostly a marketing feature, as in practice, ......
А я уж было подумал опенсорсникам чужд маркетинг
[/offtopic]

Hastya

A Session is an inexpensive, non-threadsafe object that should be used once, for a ... single unit of work
Unit of work - это название паттерна, см. книжку Фаулера.
session-per-conversation

Так тебя смущает использование транзакций для доступа к БД?
Это так называемая проблема N+1 селектов.

Еще раз. Если тебя не устраивают селекты, которые генерирует Hibernate - поправь hbm-file. Или используй другой FetchMode.
А как ты передашь не detached objects на другую машину?

Просто не передавай lazy-объекты на другую машину или используй Hibernate.initialize. Это кстати в факе неоднократно написано.

Marinavo_0507

> А я уж было подумал опенсорсникам чужд маркетинг
Скорее, им чужда Java

6yrop

Unit of work - это название паттерна, см. книжку Фаулера.
причем тут это?
 
Так тебя смущает использование транзакций для доступа к БД?

лол
 
Еще раз. Если тебя не устраивают селекты, которые генерирует Hibernate - поправь hbm-file. Или используй другой FetchMode.

нет, меня, а так же все остальных здравомыслящих людей, включая разработчиков Hibernate, не устраивает количество запросов к базе.
 
Просто не передавай lazy-объекты на другую машину или используй Hibernate.initialize.

я об этом тебе и толкую , lazy для многозвенки не подходит.

Hastya

нет, меня, а так же все остальных здравомыслящих людей, включая разработчиков Hibernate, не устраивает количество запросов к базе.
Чем это не устраивает "остальных здравомыслящих людей"?

6yrop

Чем это не устраивает "остальных здравомыслящих людей"?
200 запросов по 5 записей выполняются медленнее, чем один с 1000 записей

Hastya

200 запросов по 5 записей выполняются медленнее, чем один с 1000 записей

Откуда эти данные? методику измерения можешь привести?

6yrop

да что тут измерять то, если сами хибернейтовцы о ней пишут
Select fetching (the default) is extremely vulnerable to N+1 selects problems

Я сам видел, как это тормозит.
Майросовтовцы в DLinq тоже об этом говорят и вводят для этого оператор Including.
Если хочешь с этим разобраться до конца, действительно, проведи эксперимент, потом почитай как база выполняет INNER JOIN. Разберешься, напиши здесь, интересно будет почитать .

Hastya

Я сам видел, как это тормозит.
Если хочешь с этим разобраться до конца, возьми Oracle и проверь, что будет быстрее - join или select. Будешь неприятно удивлен.
Я сам видел, что N+1 select по кластерному индексу - может быть существенно быстрее join-а. Кроме того, ты, возможно, слышал, что такое кэш первого уровня в Hibernate.
Результаты performance зависят от настолько большого числа различных факторов, что утверждения типа "я сам видел" употреблять нет смысла.

6yrop

Если хочешь с этим разобраться до конца, возьми Oracle и проверь, что будет быстрее - join или select. Будешь неприятно удивлен.
Я сам видел, что N+1 select по кластерному индексу - может быть существенно быстрее join-а.
типа оптимизатор запросов у Oraclе-а тупит?
соглашусь, что иногда он может тупить, но это должно быть редко

Dasar

return GetAdjacentEntities("Division");
на полный ответ - разговор бы продолжал, а так мне лень вытягивать из тебя правду.
ps
где здесь поддержка редактирования (изменений)?

Dasar

> Связь многие-ко-многим реляционная модель не поддерживает (соответственно DataSet-ы тоже).
бред
для такой связи просто заводиться отдельная таблица.
> Про сильную/слабую связь не понял, когда что удаляется?

class Car
{
   Driver Driver {get;}
  
   WheelCollection Wheels {get;}
}

Car и Driver связаны слабой связью, т.к. при удалении машины водителя удалять не надо.
Колеса же удалять надо при удалении машины, даже если на эти колеса есть какие-то другие ссылки.

6yrop

где здесь поддержка редактирования (изменений)?
изменение происходит через другой конец связи
 

public class Division : Entity
{
    public Client Client
    {
     get
{
return (Client)
GetAdjacentEntity("Client");
     }
set
{
SetAdjacentEntity(value);
}
    }
  

Все как в DataSet-ах.

6yrop

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

6yrop

бред
для такой связи просто заводиться отдельная таблица.
я это и имел ввиду

bleyman

Car и Driver связаны слабой связью, т.к. при удалении машины водителя удалять не надо.
Колеса же удалять надо при удалении машины, даже если на эти колеса есть какие-то другие ссылки.
Это всё в базе записано конечно =)

6yrop

Car и Driver связаны слабой связью, т.к. при удалении машины водителя удалять не надо.
Колеса же удалять надо при удалении машины, даже если на эти колеса есть какие-то другие ссылки.
удалением можно управлять
1. перегружая метод Entity.Delete
2. выставляя у связи каскадное удаление
У меня эта проблема не стаяла. В системе придерживались линии, что записи не должны удаляться, просто был флажек IsActive = true/false.
Оставить комментарий
Имя или ник:
Комментарий: