Как стать автором
Обновить

Комментарии 112

То что надо, огромное спасибо.
Всё бы хорошо, но зачем xml, когда есть анотации? Ведь гораздо удобнее написать например
@Id
@Column(name= "id")
private Long id;


xml лишь размазывает модель по разным файлам.
Согласен. Посчитал, что в основах лучше описать с помощью xml, дабы у людей, не знакомых с этим, не возникло путаницы.
Мне кажется, что с аннотациями было бы проще и понятнее.
А вы спросите у c++'ников или php'истов - знают ли они, что такое аннотации в java.
Знаете, если C++'ник полезет править java код, он наверное спросит по то, что не знает у гугла :)
IMHO в XML менее читабельно.
зачем же по разным, весь маппинг можно засунуть в один файл.
А как быть с проектами, где persistant-классов не единицы и даже не десятки, а сотни?
конечно, на аннотациях описывать все много проще и читабельнее, но веть не об этом речь, а о том что можно. как и в других подходах здесь тоже есть свои минусы...
Но добавляет гибкости.
Я использую nHibernate - порт под .net, при интеграции с Castle Active Record можно использовать аттрибуты в коде, но тогда мапинг размазывается.

Я лично делаю класс entity, например Users.cs и к нему Users.hbm.xml.

1. Легко найти мапинг класса
2. Код не замусорен всей этой мапинг хренью, т.к., по идее интерфейс обращения с БД должен быть абстрагирован и извлечен в отдельный от бизнес логики слой infrastructure
Аннотации зашивают логику конфигурирования в бинарный код. Любое изменение конфигурации влечёт полную пересборку проекта. Это антипаттерн.
Не согласен с тем, что это - антипаттерн. Не могу представить себе ситуацию, когда нужно поменять мэппинг, но не менять класс. Даже если надо добавить поле - его надо добавить и в класс. Максимум что приходит в голову - null, not null и может быть длина строки. Но такие вещи обычно надо закладывать на этапе проектирования базы.
Привязка к схеме базы данных — ещё большая глупость.
Нужно работать с бизнеслогикой и, отталкиваясь от неё, подбирать подходящую схему БД. А так как бизнес-логика периодически изменяется, то схема БД тоже не стоит на месте.

Не нужно "политику" (к коей относится конфигурация) зашивать в логику.
А кто зашивает политику в логику?
Вы определитесь, если вы правите бизнес-логику, то вам доступны исходники. А значит никто не мешает поправить аннотации в классах-сущностях. Если же вы просто меняете схему БД, то да, достаточно поменять xml-ки не пересобирая проект, но зачем менять схему БД просто так, без сущностей?
увы, такие вещи очень часто на практике требуется поменять существенно позже этапа проектирования базы, особенно «null-not null», когда клиента вдруг осеняет, что он не совсем правильно сформулировал свои потребности)

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

Пример из другой сферы:
Вот когда-то очень давно я считал, что отдельный CSS-файл — это страшно неудобно. Ну как, так у меня вся информация о теге прямо в нём же, в атрибуте style, а тут надо куда-то в другое место лезть, там нужные классы искать... Однако, я думаю, ясно, что разделение html и css - это хорошо и полезно, поелику это есть разные аспекты описания, им и быть в разных местах, и меняться независимо.

Вот и пара «код-маппинг» (структура класса => маппинг на хранилище) аналогична в принципе паре «html-css» (структура документа => маппинг на экран). И без особых на то причин, лучше их не смешивать.
Как общий пример ORM в Java так имхо описать - лучше. Поскольку некоторые ORM(TopLink например) не особо используют аннотации.
Есть стандарт доступа к данным - JPA и он использует аннотации.
Безусловно. Но аннотации в различных проектах и различных системах используются в разном количестве. В моем текущем проекте с использованием Oracle TopLink аннотаций практически нет. А сталкиваться тем кто только начинает знакомится с этими технологиями придется с разными проектами явно. Не лучше сначала описать маппинг через xml?
А вот Toplink Essentials в Glassfish их очень даже использует.
Аннотации полностью позволяют сделать то, что можно в xml? Задавать имена индексов и прочие мелочи?
Когда я общался с хибернатом такого вроде бы нельзя было в аннотациях.
Не знаю ничего такого, что можно сделать на xml но не сделать на аннотациях, хотя не исключаю что такое может быть.
P.S. @IndexColum("index_name") ;)
Всё понял, большое спасибо.
Круто. Переименование/добавление индекса в БД -> пересборка кода бизнес-логики? ))
Каждый день переименовываете индексы?
Мне кажется, или мы говорили о разделении хранения и бизнес-логики?
Перенесите, пожалуйста, в http://habrahabr.ru/blog/java/.
Теперь Вы можете писать не только в персональный блог.
Все как бы на JPA уже переползли. Ну а вообще запихнуть тысячу страниц Java Persistence with Hibernate в один пост - слишком самонадеянно.
java-блог наполняется и это радует :)
однако мне больше нравится использовать хибернейт в обёртке GORM(Grails): ни тебе xml-конфигов, ни мильоов геттеров-сеттеров, ни фабрик с истансами - красота :)
Есть в GORM и свои проблемы, но в 99% случаев да, гораздо удобнее.
некоторые люди говорят, что GORM - самая сильная черта grails :)
И тормоза в бонус ?(:
Чем за удобство придётся платить?
хм, почему же сразу тормоза?
геттеры-сеттеры создаются при генерации байткода, тут тормозов нет
аннотации/xml-конфиги генерятся при сборке проекта, я думаю.
вот в динамических методах типа Race.findAllByCityLikeAndStateLike ещё возможен оверхед, да и то я не уверен.
А какая есть информация, чтобы из неё сделать xml или аннотации?

Я просто хочу узнать чем пожервовали ради удобства, не бывает так, чтобы ничем :(
Да ничем особо не жертвовали. Кроме статической типизации. ;)
тут возможны два варианта:
1) информации никакой не нужно - таблицы в БД генерятся по domain классам
2) легаси БД уж есть, тогда мы просто объявляем маппинг вида
static mapping = {
table 'people'
version false
columns {
id column:'person_id'
}
}
Ситауция: есть джава классы, как сгенерировать по ним схему в БД без доп информации (маппингов или аннотаций).
Я, например, не понимаю, как по джава-коду можно сгенерировать мелочи типа индексов, их имён и прочего (миграции удобней писать).
С легаси базой — всё понятно.
1) выкидываем геттеры-сеттеры для удобства и читабельности
2) пишем grails create domain-class Foo
3) в получившийся файл Foo.groovy переносим содержимое, полученное на этапе 1)
4) добавляем ограничения(constrains)
5) добавляем связи, "нестандартные" типы, "нестандартные" индексы и "нестандартные" маппинги по вкусу в пару строк того же groovy-кода в тот же groovy-класс.
далее либо пишем grails generate-all, а потом grails run-app и оцениваем получившийся полный CRUD, либо просто grails shell и получаем табличку(таблички) в БД

зы может мне в противовес hibernate осветить GORM, есть желающие?
Не знаю как всем, но мне было бы интересно про GORM узнать.

Груви немного используем, но больше как тестовое — потому как он медленней. Плюс многое (управление сессиями, транзакциями, фабриками) за нас делает за нас Spring, посему хибернат сложностью особо не напрягает.

Но способ GORM, который вы описали выглядит проще (:
grails, вообще говоря, Spring(да и hibernate) тоже использует.

кстати, насколько сильно заметна неторопливость groovy в вебприложениях?
Да, я знаю, что используется Spring, это хорошо (:

Мы груви не используем везде, есть опыт как языка скриптования и для отладок. Во многих местах мы отказались уже от Ognl, тоже из-за скорости. Порядок скоростей OGNL и Groovy думаю сходен.
c OGNL дела, увы, не имел, но groovy всё же побыстрее должен быть, думаю. Groovy вообще хорош практически идеальной интеграцией с java - в большинстве случаев .java можно превратить в .groovy с минимальными изменениями, ну а "узкие" места groovy-кода переписать на java. В groovy 1.6 скорости разработчики ещё прибавили.
Я активно использую Groovy. Поскольку в задаче узкое место - это БД, то разницы с Java практически нет.
зы может мне в противовес hibernate осветить GORM, есть желающие?

Желающие наверняка есть
Лично я с удовольствием почитаю.
Заранее благодарен
Судя по всему оверхэд будет лишь в первый раз. Потом query кэшируется.
Обычно рекомендуется из примеров убирать геттеры/сеттеры, заменяя им чем-нибудь вроде
// ...
или
// Default getters and setters
Возник такой вопрос: а почему в классе Bus вы написали
private Long route_id;

а не
private Long roprivate Route route;ute_id;

? Если так писать, то теряется половина смысла использования Hibernate :(

Если немного переписать модель (только модель, основной ваш код я пока не трогаю) на базе ваших примеров, но с небольшой переделкой путем
1) использования аннотаций (наиболее актуальный вариант на данный момент),
2) изоляции логики связанной с хранением объектов от самих объектов,
3) использования Generics,
то можно получить примерно следующее:


Собственно наши классы:
@Entity
@Table(name = "busses")
public class Bus extends ManagedEntity {
  @NotNull
  @Length(max = 6)
  private String number;  
  
  @NotNull
  @ManyToOne
  @JoinColumn(name = "fk_route")
  private Route route;
  
  @OneToMany(mappedBy = "driver")
  private Set<Driver> drivers;

  // ... 
}


@Entity
@Table(name = "drivers")
public class Driver extends ManagedEntity {
  @NotNull
  @Length(max = 20)
  private String name;
  
  @NotNull
  @Length(max = 20)
  private String surname;
  
  private int age;
  
  @OneToMany(mappedBy = "bus")
  private Set<Bus> busses;
  
  // ... 
}


@Entity
@Table(name = "routes")
public class Route {
  @NotNull
  @Length(max = 30)
  private String name;
  
  @NotNull
  private int number;
  
  @OneToMany(mappedBy = "bus")
  private Set<Bus> busses;
  
  // ...
}



ManagedEntity это класс-предок для наших persistant-объектов:
@MappedSuperclass
public class ManagedEntity extends VersionedEntity {
  public static final long NULL_LONG = 0L;

  @Id
  @GeneratedValue
  @Column(name = "id")
  @NotNull
  private long id = NULL_LONG;
  
  // ...
}



А VersionedEntity - будет обеспечивать оптимистическую блокировку:
@MappedSuperclass
public abstract class VersionedEntity implements Serializable {
  @Version
  @NotNull
  @Column(name = "obj_version")
  private long objVersion;

  // ...
}



Note: аннотацию @Column я почти всюду опустил, чтобы не засорять пример. По дефолту, если этого аттрибута нет, Hibernate будет использовать то же имя, что и имя поля объекта. А так как у нас имя столбца в таблице всюду совпадает с именем поля у объекта, то можно было @Column вообще не использовать.


Мне кажется, что такой код намного нагляднее, чем вариант с заданием маппинга в XML. Хотя некоторые минусы у этого варианта тоже есть.
Там в самом начале вместо этой абракадабры
private Long roprivate Route route;ute_id;

должно было быть
private Route route;
Спасибо за такой четкий комментарий. Сам сейчас перехожу на использование аннотаций, вынес для себя кое что полезное.
НЛО прилетело и опубликовало эту надпись здесь
Спасибо за комментарий, возьму на заметку.
И где же здесь изоляция хранения? Видна только лапша из бизнес-классов, ограничений на значения полей, названий столбцов в БД и внешних ключей.
Здесь под "изоляцией хранения" понимался тот факт, что из самих бизнесс классов была убрана и вынесена в отдельный класс такая вещь, как id.
Объём написанного кода для такой простой задачи уж очень большой и отпугивает от Hibernate. С использованием анотаций уже лучше, но все равно много. А можно этот пример реализовать во всю "мощь" Hibernate, чтобы оценить все его преимущества?
P.S. Например, если этот пример переписать на Ruby с ActiveRecord, то кода будет до неприличия мало.
К этому можно добавить HibernateSearch добавляя на нужные домены аннотации и получая классный поиск с автоматическим обновлением индекса при CRUD. А также возможность поднять всё это в кластере. В Eclipse можно установить плагин и делать HQL запросы напрямую в БД. Распределённые транзакции через JTA, кеширование доменов (в том числе в кластере). И туча тонких настроек и фич, которые не доступны в Django или RoR, и с помощью которых можно затюнить ORM под свои нужды.
И самое инетерсное - кэширование.
Также в Hibernate удобно создавать свои типы данных, назначая им правила мэппинга, приятной фичей являются так называемые компоненты и много других вкусностей.
Ах, да, забыл еще такой удобный инструмент, как hibtools
А зачем? Все тонкие настройки в чистый сиквел. ORM для чего? Для замены сиквела или для удобства работы над частями, где он сложен? Когда ORM сложнее сиквела он мешает.
Тонкие настройки именно по ORM маппингу и выборке доменов, а не по SQL.
НЛО прилетело и опубликовало эту надпись здесь
А вот когда количество табличек перевалит за пару десятков, вот тогда голый SQL будет кошмаром.

А если вдруг понадобиться переименовать поле в табличке или поменять его тип, то с голым SQL это будет очень интересное занятие.
НЛО прилетело и опубликовало эту надпись здесь
Простая?.. В паре десятков мест поменять это разве просто… С hibernate я имею статическую проверку типов при переименовании. Возмем еще, например, вариант, когда надо поле перенести из одной таблички в другую.

Лично я боюсь голого SQL по банальной причине — лень. Лень изобретать велосипед. Есть очень большое желание писать

#{order.client.fullName}, а не #{listItem[1]} :)

Особенно, если нужно выводить не список order'ов, а детали order'а.

Конечно, есть свои глюки, часто работает медленнее, чем голый SQL из-за того, что вытаскивает больше полей, чем необходимо, но в большинстве случаев удобство при программировании перевешивает.

вот было не плохо сделать сделать небольшой обзор всех этих фич
Надо бы сделать, но времени пока нет. Еще имеет смысл рассмотреть такие системы как Tapestry5 и Wicket. И в целом описать текущее положение дел в java, а то все кричат что в java много классных фреймворков и библиотек (а это правда), но к сожалению никто не делает хороших review по ним... Как у меня появится время обязательно займусь всем этим.
почитаю с удовольствием
если вам нужна мощь hibernate вкупе с простой настройкой и простым использованием, советую взглянуть на GORM:
_http://grails.org/GORM
спасибо, посмотрю для общего развития
На самом деле код примеров мог быть намного компактнее. Например реализация метода getBussesByDriver (см. выше) могла состоять всего из одной строчки:
return driver.getBuses();
Действительно так, зато хоть немного HQL-я заюзали. Держите плюс! :)
Тема статьи хорошая, гораздо лучше чем про стартапы и как заработать миллион.
Но ИМХО, лучше все-таки писать о том в чем разбираешься, а не начинаешь разбираться.
Не согласен. Если взять большую тему - хибернейт то в ней человек может еще разбираться, в то же время в основах (банально - как написать мэппинг) он уже разобрался. Почему бы ему об этом не написать?
Потому что он банально не справится.
Без глубокого владения темой не получится выделить важные моменты и подать их структурированно.
Есть несколько типов статей: тонкости (которые должен описывать опытный) и начало, побуждающая — вторые вполне могут писать начинающие, им проще — они только что это пережили.
Да ладно вам ребята, все с чего-то начинают, будто у нас тут на хабре статьи только старые бородатые программисты пишут - ничего подобного :)
НЛО прилетело и опубликовало эту надпись здесь
Если не ошибаюсь, Doctrine вроде как а-ля ActiveRecord (из RoR). Как он по скорости/потреблению ресурсов ?
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
В нативном sql только так как ты написал, в hibernate можно так
List bookIds = ....
Query query = session.createQuery ("from books where books_id in (:booksId)");
query.setParameterList("bookId", bookIds);
НЛО прилетело и опубликовало эту надпись здесь
Оговорка, под нативным sql я имел ввиду при использование JDBC, короче не так выразился.
А еще в Hibernate есть классная вещь - Criteria API, мне кажется в большинстве случаев удобнее и логичнее чем HQL
Статья хорошая, все просто и понятно, спасибо.
Пара мелких замечаний:
- busses -> buses
- private Long route_id; -> private Long routeId; согласно Java нотации. Или я не прав?
- DAO классы не должны ничего знать о Swing
- имена пакетов всегда пишутся маленькими буквами.
- геттеры getBusDAO и подобные с capital case в названиях полей выглядят убого и не соответствуют Java naming conventions.
Очень радует появление джавы.
Спасибо.
Геттеры/сеттеры и конструктор по умолчанию это не из Java Naming Conventions, а из соглашений Java Beans
Немного не в тему, но JOptionPane.showMessageDialog с первым параметром "null" это плохо, лучше сразу отучать себя от такого
я бы еще посоветовал вынести работу с сессией и транзакциями в отдельное место
Например в интерсептор или обернуть вызовы методов в замыкания
Как вариант — вынести это, например, в Spring :)
это самый лучший вариант )
но, думаю, для одной статьи этого многовато )
Огромное человеческое спасибо за статью!
Как полагается, ложка дегтя.

Как это ни странно, Hibernate плохо приспособлен для функционирования в среде веб, особенно если вы не пользуетесь EJB контейнером. Проблема в том, что связанные поля и коллекции с lazy fetching не могут использоваться за пределами сессии. Например если в примере автора поле Bus.drivers замепить как lazy, то

BusDAO.getBusById( ... ).getDrivers().get( ... )

не выдаст водителя автобуса, поскольку обращение к полю drivers (и фетчинг коллекции) лежит за пределами сессии. Это происходит всегда, когда вы используете, например, любой mvc фреймворк. В этом случае фетчинг lazy полей может происходить не только в action, но и в момент рендеринга страницы.

Как возможное решение можно написать фильтр для Tomcat, который до обработки запроса открывает новую hibernate-сессию и записывает ее как атрибут в объект request, а после обработки делает commit и закрывает ее.
Собственно отдельная сессия под каждый запрос (как у автора) - это, конечно, не корректно. Обычно на один запрос к серверу - одна сессия Hibernate (да и транзакция в большинстве случаев - одна).
Статья хорошая, наверное больше для начинающих.

Я вот когда начинал разбираться с HBM, точнее с его воплощением под .NET взял и сделал помимо мапинга классов(для удобного Create\Save\Update\Delete ОДНОГО эклемента) и всю логику на нем (импорт\экспорт данных\запросы\сортировки и тд) - это была моя главная ошибка - т.к HBM дико медленно работает, нет когда вы достаете один элемент и его , допустим, даллее редактируете это еще нормально, но вот когда вы пытаетесь сделать выборку хотя бы по 10000 тыс элементов(каждый из которых представляет собой достаточно большое дерево - порядка 60 таблиц), или экспортировать из XML(5мб) файла данные в HBM классы, а потом в базу
>Заметьте, что все классы сущностей должны соответствовать Java naming conventions, т.е. у них должны быть обязательно геттеры, сеттеры и конструктор по умолчанию. Ничего сложного :)

:-OOOOO

То есть ничего сложного в тысячах ненужных строк кода в том случае, когда объекты содержат не пару, а сотню полей???

Господа, извините не удержался - это бред! Это ненужная работа! Написана куча кода для какой цели? Сохранить структуру в Java-класс? Вы хотя бы для себя решили вопрос - зачем Вам нужно написать bus.number вместо recordset("number")?

Вы проделали огромную работу, создали сложную конфигурацию, которую придется поддерживать, привязали свой код максимально к данным (при добавлении поля его придется менять) и? Зачем??

Вам просто нравится работать? Где выгода-то?

Вот смотрите:

RecordSet rs = SELECT("SELECT * FROM BUS");

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

Вот вывел номер автобуса:

System.print(rs("number"));

Все что мне нужно - коннект к SQL RDBMS. И все! И код максимально свободен от изменения данных.

Не занимайтесь ерундой, короче. Будьте проще.
Все эти "тысячи строк ненужного кода" генерируются срезствами IDE за пару секунд :)
А работать напрямую с базой хорошо, когда у вас
1) очень простая бизнес-логика,
2) нет сложной валидации данных,
3) низкие требования к производительности.
Из-за этого они не перестают быть тысячами строк ненужного кода.

А кто сказал, что мой метод - это работа "напрямую" с БД? Кто мне мешает закешировать эти датасеты на клиенте?

Насчет производительности говорить бессмысленно. Отдельные решения от hibernate могут замедлится, отдельные - ускориться.
4)маленькая команда (SQL запросы люди могут писать по разному)
5)одна и таже база (в смысле тип MS SQL или oracle, c HBM очень легко менять тип базы)
Ну во-первых, SQL запросы в hibernate чудовищны просты - это SELECT по уникальному идентификатору и UPDATE по нему же.

Вот пусть один программист БД и пишет SQL, а остальные его используют.

Насчет базы - мей би.

Понимаете я не представляю себе проекта (серьезного), в котором можно взять и заменить базу. Мы в свое время пытались переползти с MS SQL на ORACLE, но поняли быстро, что это нереально. Слишком много работы, слишком много специфических особенностей использовано и т.д....
Низкие требования к производительности - это как раз для hibernate. Он хорош для быстрого старта, для создания прототипа или для небольшого проекта. Мне больше нравится ibatis - сохраняет свободу дейсвтий. Время проведенное за тюнингом и доводкой hibernate практически нивелирует разницу между написанием сиквел-запросов. А так мне нравится в hibernate кэш и работа с сессией. Но то что он сам генерит запросы - это минус.
Это не минус. Это плюс. Это всё ради того, чтобы обеспечить высокую совместимость. И опять же, Хибернейт предоставляет возможность использовать нативные SQL-запросы, если это нужно. Другое дело, что реальная необходимость возникает действительно редко. А собственно HQL - это обобщенный SQL, который Хибернейт сможет подогнать к любой БД.

У меня был опыт миграции с MySQL на Oracle без Хибернейта и с Хибернейтом. В первом случае мне пришлось вносить изменения чуть ли не в половину более-менее серьезных запросов. Во втором случае оказалось достаточно прикрутить нужный драйвер и подправить конфиг.

Что касается производительности. Если речь идет о проекте на миллионы пользователей, то тут конечно Хибернейт будет скорее мешать, чем помогать. В такие приложениях нужно всегда писать запросы максимально заточннные под конкретную задачу и конкретную БД. Если же речь идет о бизнес-приложении небольшого и среднего масштаба, то только за счет кэширования производительность вырастает в несколько раз.
1. Любая предметная область состоит из сущностей и отношений между ними, а не из каши атрибутов. Поэтому оперировать объектами удобнее и правильней, нежели полями.
2. В ORM вы определяете структуру данных и отношения ОДИН РАЗ, и не задумываетесь при выборке данных. В SQL же вы в каждом запросе цепляете абсолютно глупый компот из JOIN и заново указываете связи (несмотря на то, что структура уже определена DDL).
3. Hibernate-реализация не зависит от движка БД. Чтобы перейти на новый движок вам не нужно будет перелопачивать тонны кода, достаточно поменять пару строчек в конфигурации. Более того, к Hibernate можно прикрутить сторонние движки, например Lucene.
4. Hibernate позволяет в простой форме реализовать наследование.
5. Кеш данных, кеш второго уровня и прочие вкусности.
6. При переименовании таблиц/полей не придется апдейтить все запросы (количество которых может быть вырасти до тысяч), а достаточно лишь поменять меппинг.

А теперь самое главное:
bus.getDrivers() намного проще, чем
SELECT * FROM drivers, busdriver WHERE drivers.driver_id = busdriver.driver_id AND bus_id = xxx

В добавок, в IDEs типа Eclipse при вводе "bus." вылезет полный список полей объекта. В SQL же запросах постоянно придется консультировать правильное написание полей в структуре данных.
То есть ничего принципиального нового не появляе тся, а сложность и объём возрастает? Всё это можно было сделать в три раза меньше используя только базовое знаение SQL. И это было понятно каждому. А в этой мути без понимания чудо-hibernate не разберёшься. Плюс несколько дополнительных шагов в сосздании работаебщего проекта (все эти танцы с XML) не факт, что положительно скажутся на простоте отладки и поддержки.
"1. Любая предметная область состоит из сущностей и отношений между ними, а не из каши атрибутов. Поэтому оперировать объектами удобнее и правильней, нежели полями."
Именно так. Но для этого вы и пишене на Java, а не GW-BASIC. Все те же сущности реализуются и при меньшем числе телодвижений.
"2. В ORM вы определяете структуру данных и отношения ОДИН РАЗ, и не задумываетесь при выборке данных. В SQL же вы в каждом запросе цепляете абсолютно глупый компот из JOIN и заново указываете связи (несмотря на то, что структура уже определена DDL)."
Как-то плохо согласуется с ООП. для работы с такого рода данными вам нужно три-вида запросов - инкапсулируйте их в объект. Опять же, объём кода меньше, сложность меньше, телодвижений меньше, понятность больше.
"3. Hibernate-реализация не зависит от движка БД. Чтобы перейти на новый движок вам не нужно будет перелопачивать тонны кода, достаточно поменять пару строчек в конфигурации. Более того, к Hibernate можно прикрутить сторонние движки, например Lucene."
Тем, кто пишет программы (тем более реализиующие столь просте отношения) зависящие от движка БД никакой hibernate не поможет. Как я уже говорил - тут несколько запросов - все замечательно укладывается в страницу кода и бедет полная независимость от БД. Используя hibernate вы лишь пытается уйти от ручного написания это кода (котрый пишется один раз), за счёт странных танцев с XML, но сложность от этого только возрастает - используется две дополнительных технологии (XML и hibernate) плюс крайне сомнительная наглядность результата (который кстати с трудом ложится в идеологию ООП).
"4. Hibernate позволяет в простой форме реализовать наследование". Т.е. все эти мутные class-factory это "простая форма"? Наследование можно реализовать намного проще. тем более в Java.
"5. Кеш данных, кеш второго уровня и прочие вкусности."
Тут совсем не понял. Как можно ускорить выборку из БД не нарушая целостность - не понятно. Хотя допускаю.
"При переименовании таблиц/полей не придется апдейтить все запросы (количество которых может быть вырасти до тысяч), а достаточно лишь поменять меппинг."
Шутите? Вы, что все SQL запросы в своих программах руками пишите и сто раз поторяете если придётся?! При правильной структуре программы при переименованеии полей нужно лишь изменить одну-две строчки кода и собственно саму базу.
"А теперь самое главное:
bus.getDrivers() намного проще, чем
SELECT * FROM drivers, busdriver WHERE drivers.driver_id = busdriver.driver_id AND bus_id "
Т.е. после всех вот тех промежуточных классах проще? :) Т.е. инкапсуляция SQL в отдельный класс и реализация всей вон той мути прямо в классе bus это сложнее? :))))
"В добавок, в IDEs типа Eclipse при вводе "bus." вылезет полный список полей объекта. В SQL же запросах постоянно придется консультировать правильное написание полей в структуре данных."
Нет, правда, скажите, что Вы не серьёзно!!! Или хотите, я вам продам за сто тыщ мульёнов идею, как не писать в каждом методе SQL код? :)))))
> То есть ничего принципиального нового не появляе тся, а сложность и объём возрастает? Всё это можно было сделать в три раза меньше используя только базовое знаение SQL.

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

2. ООП здесь не при чем. Зачем делать каждый раз то, что машина должна уметь делать сама (я имею ввиду написание запросов). Структура данных ей известна, необходимые данные - тоже. В чем проблема?
3. Это был только пример. В Hibernate 3 можно обойтись без XML при помощи аннотаций (см. коментарии выше). Как говорится, тяжело в учении - легко в бою. Один раз попотев над структурой и меппингом, манипуляция с данными становится очень простой и наглядной.
4. Здесь мы говорим не о самом наследовании, а о его персистенции в базе данных. Наследование-то вы сделали, а кто сохранять его будет?

> Нет, правда, скажите, что Вы не серьёзно!!! Или хотите, я вам продам за сто тыщ мульёнов идею, как не писать в каждом методе SQL код? :)))))
Посмотрите коммент от пользователя Regis.
http://habrahabr.ru/blog/java/47258.html#comment1011773
Если Вы мне предложите что-нибудь проще и короче, то я возьму все свои слова обратно.
Простите, а Вы что, динозавр?
Вот холивар развели )))

HB тормозит - это даже я могу точно, использование кэша спасает, но не особо, иногда когда точно уверен в чем-то, то можно отключить транзакции при сохранении (ускоряет примерно в 10 раз процесс)

Ошибки в Hibernate сложнее отследить.

НО HBM это лишь путь эволюции ООП под БД, не знаю уместно ли сравнение, но все-таки на asmе можно написать идеальную программу, которая будет оптимизирована идеально и даст вам полную свободу действий, но все почему-то пишут приложения под Java, С# и с++
А вот скажите пожалуйста, какая область применения Hibernate? Я имею ввиду в проектах какого масштаба? Сайты писать на это штуке 100 процентов изврат=) Очевидно что для штук потяжелее. Только я почему-то всегда думал что в крупных проектах с огромными базами и ограничениями не более 0,01 секунды на простой запрос твикают непосредственно SQL и используют по максимуму процедурные фишки скажем Oracle.
Область применения такая что, в крупных проектах со схемой в полсотни таблиц, хибернэйт как раз и позволяет объеденить схему бд с объектной моделью приложения. А это, имхо, большое дело.
В тоже время никто не мешает юзать хранимые процедуры под конкретную субд вкупе с хибернэйтом.
Вы немного не поняли мой вопрос. Я как бы не спрашивал зачем нужен ORM («позволяет объединить схему бд с объектной моделью приложения»), а зачем именно такой сложный в использовании ORM. Просто отразить таблички в объекты и обратно можно без всего этого ужаса и тон кода, примеры — Grails/Gorm, Rails/ActiveRecord.
Ссылочки поправьте, пожалуйста=) (на дамп и на библиотеки с файлами) За статью спасибо!
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации