Зрелость J2EE
А они не закрывают. Если ты внимательно почитаешь что-нибудь хорошее и правильное про Hibernate, например Hibernate in Action, то ты прочтешь там, что создатели Hibernate вовсе не позиционируют его как "средство от всех болезней". SQL никто не отменял. Hibernate имеет вполне определенную нишу. Это OR mapper. Средство для отображения графа объектов на таблицы реляционнной СУБД. Это не означает, что все надо делать с его помощью. Запросы для генерации отчетов например, не стоит писать на HQL. В общем, косяка нет. Что касается цитаты, то в ней имеется в виду, что ты можешь через Hibernate исполнять свои драгоценные SQL запросы, а он позаботится о преобразовании ResultSet в объекты.
2. Если можно пользоваться SQL, то сложно будет следить за переносимостью на другую СУБД. Кто будет следить (да и как что один из разработчиков не напишет SQL специфичный для конкретной СУБД? А люди часто ведутся на то, что при использовании Hibernate, приложение будет переносимо.
"средство от всех болезней"
если есть механизмы, которые дублируют друг друга, это всегда плохо. Архитектура должна освобождать программиста от технических деталей, у него не должно быть выбора -- на осмысленный выбор всегда тратиться время.
В общем, косяка нет. Что касается цитаты, то в ней имеется в виду, что ты можешь через Hibernate исполнять свои драгоценные SQL запросы, а он позаботится о преобразовании ResultSet в объекты.
присвоить п переменным значения, да это офигенно сложная задача
![](/images/graemlins/wink.gif)
Средство для отображения графа объектов на таблицы реляционнной СУБД.Зачем это надо? тем более такое мострообразное как Hibernate?
Чтобы уменьшить время, которое тратиться на кодирование этого отображения
зачем отображение вообще нужно?
наверно люди хотят одновременно с одной стороны свои бизнес объекты, а с другой стороны функциональность датасетов
кстати, Hibenate как реализация OR под DLinq ой как подойдет
Ты можешь руками насоздавать классов и понопесать селектов, чтобы их заполнить данными, а также апдейтов, инсертов и делитов, чтобы сохранить изменения обратно в базу (этот муторный и неинтеллектуальный этап более-менее галимо делает студия 2005).
Либо ты можешь Hibernate попросить построить тебе набор классов с автоматически сгенеренными селектами и прочими командами для работы с базой и почти думать о том, как объекты сохранятся в базу.
И даже ходют слухи, что Hibernate умеет генерить скрипты для создания БД по иехархии классов.
И даже что-то умеет делать, чтобы адекватно реагировать на изменения объектной модели и/или структуры БД.
![](/images/graemlins/wink.gif)
Про селекты надо говорить по-подробнее, но там тоже у Hibernate спорные преимущества.
Это похвально.
Для начала почитай про Criteria API, Collections и Tuning Fetch Strategies.
Синхронизация со схемой БД в Hibernate имеется, есть такой ключик HBM2DDL_AUTO, поддерживающий несколько режимов, в том числе простейший create-drop.
"Прелести реляционной модели" это хорошо сказано, Hibernate как для того и был создан, чтобы эти прелести убрать подальше, и надо сказать, они достигли в этом больших успехов.
С DataSet-ами не знаком, но в Hibernate есть такая штука как Entity Mode, которая позволяет "дегидрировать" записи в dynamic maps или XML.
Либо ты можешь Hibernate попросить построить тебе набор классов с автоматически сгенеренными селектами и прочими командами для работы с базой и почти думать о том, как объекты сохранятся в базу.Hibernate генерит select'ы на ходу
и не обязательно он будет генерить тебе классы, это делает Hibernate Tools. а так же реверс инжениринг базы или наоборот, создание ddl для базы по описаниям классов
Hibernate позволяет работать в проге чисто с твоими объектами, сохраняя их в неком хранилище и подгружая их оттуда
![](/images/graemlins/grin.gif)
Читал я это всё, не впечатлило
![](/images/graemlins/confused.gif)
Criteria APIВ J2EE Criteria, кажется, вообще нет.
Collectionsэто к чему ты написал?
Hibernate Toolsа там не требуется Tools for Hibernate Tools?
![](/images/graemlins/grin.gif)
Hibernate генерит select'ы на ходуага по HQL селекту генерит SQL селект. Очень за него рад, а может он еще и в шахматы умеет играть?
Читал я это всё, не впечатлилоТебя не впечатило, что твои любимые DataSets являются примерно 10% возможностей Hibernate?
Тебя не впечатило, что твои любимые DataSets являются примерно 10% возможностей Hibernate?по частям эти технологии вообще нельзя сравнивать. Они решают оду проблему, но по-разному, можно сравнивать только насколько успешно они ее решают.
Я не говорил, что DataSet-ы мне нравятся
![](/images/graemlins/grin.gif)
тебе понравилось?
редактор данныха что это?
программа для ввода и изменения структурированной информации
![](/images/graemlins/grin.gif)
На основе этого можно делать какие-то выводы?
Какое кол-во строчек кода у тебя приходилось на единицу функционала (например, на одно прикладное свойство)?
Какое кол-во строчек кода у тебя приходилось на единицу функционала (например, на одно прикладное свойство)?одна на get, одна на set. Я писал эти строчки вручную (в Hibernate строк все равно больше
![](/images/graemlins/smile.gif)
для полей-ссылок, и полей- массивов тоже по одной строчке?
да
ps
сильная связь требует удаления самих объектов, слабая - нет
public IEntityCollection GetDivisions
{
return GetAdjacentEntities("Division");
}
Связь многие-ко-многим реляционная модель не поддерживает (соответственно DataSet-ы тоже). Я считаю, она и не нужна, без нее удается работать единообразно, и при этом сохраняя целостность данных, что нельзя сказать о подходе, который использует коллекции связанных сущностей внутри сущностей, в частности, в Hibernate (чтобы пояснить это могу привести пример).
Про сильную/слабую связь не понял, когда что удаляется?
что нельзя сказать о подходе, который использует коллекции связанных сущностей внутри сущностей, в частности, в Hibernate (чтобы пояснить это могу привести пример).Раз уж ты критикуешь Hibernate, то поясни. Того, что ты написал, очень мало. Я не вижу ни наследования, ни lazy-коллекций, ни кэширования, ни dirty checking, ни каскадности. Ту функциональность, которую ты перечисляешь, реализовывал еще 5-летней давности проект Turbine.
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-приложения (с точки зрения обмена данными фактически одноуровневые приложения).
ни наследованияэто сейчас лень обсужать
![](/images/graemlins/smile.gif)
ни кэширования, ни dirty checking, ни каскадности.
в простой парадигме этого всего не нужно
![](/images/graemlins/smile.gif)
![](/images/graemlins/grin.gif)
2. Hibernate разделяет понятия сессии (Unit of work) и транзакции. Я не понял, к какому варианту управления сессиями относится приведенный тобой кусок кода. Видимо, имеется в виду ручное управление транзакциями, а parent - detached?
Если у нас много экземпляров parent-ов и у всех вызываем getChilds то lazy-подгрузку использовать нельзя, а в запросе надо указывать, что надо еще грузить child-ов.
Не понял. Где это нужно указывать? в каком запросе? Ты просто вызываешь getChilds остальное за тебя делает Hibernate. Или вопрос по оптимизации SQL-кода, который генерирует Hibernate?
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.
Я не понял, к какому варианту управления сессиями относится приведенный тобой кусок кода.session-per-conversation
а parent - detached
нет. Если detached, еще надо делать attach
![](/images/graemlins/confused.gif)
Не понял. Где это нужно указывать? в каком запросе? Ты просто вызываешь 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.
Я не совсем понял, что почему это имеет смысл "только в 2х-уровневой архитектуре".потому что "Hibernate does not support lazy initialization for detached objects.". А как ты передашь не detached objects на другую машину?
Прикольно встретить в документации по Hibernate вот такую фразу
![](/images/graemlins/grin.gif)
Please note that this is mostly a marketing feature, as in practice, ......А я уж было подумал опенсорсникам чужд маркетинг
![](/images/graemlins/grin.gif)
[/offtopic]
A Session is an inexpensive, non-threadsafe object that should be used once, for a ... single unit of workUnit of work - это название паттерна, см. книжку Фаулера.
session-per-conversation
Так тебя смущает использование транзакций для доступа к БД?
Это так называемая проблема N+1 селектов.
Еще раз. Если тебя не устраивают селекты, которые генерирует Hibernate - поправь hbm-file. Или используй другой FetchMode.
А как ты передашь не detached objects на другую машину?
Просто не передавай lazy-объекты на другую машину или используй Hibernate.initialize. Это кстати в факе неоднократно написано.
Скорее, им чужда Java
Unit of work - это название паттерна, см. книжку Фаулера.причем тут это?
Так тебя смущает использование транзакций для доступа к БД?
лол
![](/images/graemlins/grin.gif)
Еще раз. Если тебя не устраивают селекты, которые генерирует Hibernate - поправь hbm-file. Или используй другой FetchMode.
нет, меня, а так же все остальных здравомыслящих людей, включая разработчиков Hibernate, не устраивает количество запросов к базе.
Просто не передавай lazy-объекты на другую машину или используй Hibernate.initialize.
я об этом тебе и толкую
![](/images/graemlins/smile.gif)
нет, меня, а так же все остальных здравомыслящих людей, включая разработчиков Hibernate, не устраивает количество запросов к базе.Чем это не устраивает "остальных здравомыслящих людей"?
Чем это не устраивает "остальных здравомыслящих людей"?200 запросов по 5 записей выполняются медленнее, чем один с 1000 записей
200 запросов по 5 записей выполняются медленнее, чем один с 1000 записей
Откуда эти данные? методику измерения можешь привести?
Select fetching (the default) is extremely vulnerable to N+1 selects problems
Я сам видел, как это тормозит.
Майросовтовцы в DLinq тоже об этом говорят и вводят для этого оператор Including.
Если хочешь с этим разобраться до конца, действительно, проведи эксперимент, потом почитай как база выполняет INNER JOIN. Разберешься, напиши здесь, интересно будет почитать
![](/images/graemlins/smile.gif)
Я сам видел, как это тормозит.Если хочешь с этим разобраться до конца, возьми Oracle и проверь, что будет быстрее - join или select. Будешь неприятно удивлен.
Я сам видел, что N+1 select по кластерному индексу - может быть существенно быстрее join-а. Кроме того, ты, возможно, слышал, что такое кэш первого уровня в Hibernate.
Результаты performance зависят от настолько большого числа различных факторов, что утверждения типа "я сам видел" употреблять нет смысла.
Если хочешь с этим разобраться до конца, возьми Oracle и проверь, что будет быстрее - join или select. Будешь неприятно удивлен.типа оптимизатор запросов у Oraclе-а тупит?
Я сам видел, что N+1 select по кластерному индексу - может быть существенно быстрее join-а.
![](/images/graemlins/wink.gif)
соглашусь, что иногда он может тупить, но это должно быть редко
return GetAdjacentEntities("Division");на полный ответ - разговор бы продолжал, а так мне лень вытягивать из тебя правду.
ps
где здесь поддержка редактирования (изменений)?
бред
для такой связи просто заводиться отдельная таблица.
> Про сильную/слабую связь не понял, когда что удаляется?
class Car
{
Driver Driver {get;}
WheelCollection Wheels {get;}
}
Car и Driver связаны слабой связью, т.к. при удалении машины водителя удалять не надо.
Колеса же удалять надо при удалении машины, даже если на эти колеса есть какие-то другие ссылки.
где здесь поддержка редактирования (изменений)?изменение происходит через другой конец связи
public class Division : Entity
{
public Client Client
{
get
{
return (Client)
GetAdjacentEntity("Client");
}
set
{
SetAdjacentEntity(value);
}
}
Все как в DataSet-ах.
на полный ответ - разговор бы продолжал, а так мне лень вытягивать из тебя правду.а мне лень вычленять так, чтобы это было кратко, понятно и не вызывало лишних вопросов. Могу прислать эту часть проекта при условии не передавать третьим лицам.
бредя это и имел ввиду
для такой связи просто заводиться отдельная таблица.
Car и Driver связаны слабой связью, т.к. при удалении машины водителя удалять не надо.Это всё в базе записано конечно =)
Колеса же удалять надо при удалении машины, даже если на эти колеса есть какие-то другие ссылки.
Car и Driver связаны слабой связью, т.к. при удалении машины водителя удалять не надо.удалением можно управлять
Колеса же удалять надо при удалении машины, даже если на эти колеса есть какие-то другие ссылки.
1. перегружая метод Entity.Delete
2. выставляя у связи каскадное удаление
У меня эта проблема не стаяла. В системе придерживались линии, что записи не должны удаляться, просто был флажек IsActive = true/false.
Оставить комментарий
6yrop
Удивляет, что в технологии, которой уже не один год, и которая позиционируется как платформа для создания мегасложных бизне-приложений, есть вот такой косяк. В языке запросов (речь идет Query Language, который описан в спецификации J2EE, и который очень близок к HibernateQL) нельзя использовать подзапросы во FROM-е. Там есть сноска, в которой говориться, что подзапросы во FROM-е будут рассмотрены в следующих релизах. Но вряд ли у них получиться сделать это просто, если не делать точную кальку с SQLВ реляционной теории свойство замкнутости -- результат запроса можно использовать в качестве аргумента другого запроса -- является основным свойством реляционной алгебры, и SQL поддерживает это свойство.
Вообще странно все это, Hibernate, а следом за ним и J2EE, закрывают нам прелести реляционной модели и SQL-я. Но зачем?