О Java ORM — различия между версиями

Материал из YourcmcWiki
Перейти к: навигация, поиск
м
 
(не показано 11 промежуточных версий этого же участника)
Строка 2: Строка 2:
  
 
Плюсы:
 
Плюсы:
* Умеют дохрена всего :)
+
* Наиболее «каноничный» Java ORM
* В Hibernate есть Envers, из коробки умеющий логгировать историю изменений сущностей в отдельные таблицы
+
* Есть дополнительные фичи — например, в Hibernate есть Envers, из коробки умеющий логгировать историю изменений сущностей в отдельные таблицы
* Для получения красивого Fluent API запросов вместо HQL/JPQL-литералов можно подключить [http://www.querydsl.com/ Querydsl]
+
  
 
Минусы:
 
Минусы:
* Немного монструозны (перегружены функционалом).
+
* Код не лаконичен. Нужно задавать маппинги, классы сущностей, конструировать запросы либо через строковой HQL/JPQL, либо через многословный Criteria…
 +
* Трудно использовать для динамических сущностей (объектов произвольной структуры) — так или иначе нужно конфигурировать маппинг, даже если используется динамическое отображение без классов моделей.
 
* Возможно, не вполне идеальна логика отображения — конструирование объекта всегда связано с десериализацией, для сохранения ID связанных объектов без самих объектов применяются proxy-классы и ленивая подгрузка (нет возможности одно и то же поле, скажем, person_id, видеть и в виде ID, и в виде объекта)…
 
* Возможно, не вполне идеальна логика отображения — конструирование объекта всегда связано с десериализацией, для сохранения ID связанных объектов без самих объектов применяются proxy-классы и ленивая подгрузка (нет возможности одно и то же поле, скажем, person_id, видеть и в виде ID, и в виде объекта)…
* HQL/JPQL — всё-таки недоразумение. Не могу понять смысл реализации собственного строкового языка запросов — SQL если уж во что-то заворачивать, то во что-то объектно-структурированное — хотя бы в объект типа «запрос» с полями tables, where, order by, group by и т. п., но не снова в строковой же литерал!
+
* HQL/JPQL — всё-таки недоразумение. Не могу понять смысл реализации собственного строкового языка запросов — SQL если уж во что-то заворачивать, то во что-то объектно-структурированное — хотя бы в объект типа «запрос» с полями tables, where, order by, group by и т. п., но не снова в строковой же литерал! Кроме того, к нему есть различные [https://virgo47.wordpress.com/2014/10/09/jpa-is-it-worth-it-horror-stories-with-eclipselink-and-hibernate/ претензии].
* Объекты запросов есть в виде Criteria, но они не очень удобны.
+
  
 
== [https://github.com/ActiveJpa/activejpa ActiveJPA] ==
 
== [https://github.com/ActiveJpa/activejpa ActiveJPA] ==
  
Реализация Active Record поверх JPA.
+
Попытка реализации Active Record поверх JPA.
 +
 
 +
Минусы:
 +
* Велосипедик.
 +
 
 +
== [http://www.querydsl.com/ Querydsl] ==
 +
 
 +
Типобезопасное (импортирующее схему в Java классы) Fluent API построения SQL-запросов.
 +
 
 +
Плюсы:
 +
* API построения запросов довольно удобное.
 +
* Универсальный, работает как с JPA, так и с голым SQL.
 +
 
 +
Минусы:
 +
* Хоть и может возвращать DTO’шки (кроме обычного Tuple), они не является ActiveRecord’ами, то есть никакой логики их обновления или подгрузки связей нет. То есть, скорее должен рассматриваться как дополнение к мапперу.
 +
 
 +
== [http://www.jooq.org/ jOOQ] ==
 +
 
 +
Плюсы:
 +
* Легковесный Fluent API + Active Record фреймворк.
 +
* Похож на Querydsl, тоже использует кодогенерацию и типобезопасные запросы через Fluent API, однако в дополнение к этому генерирует классы моделей (Active Record) и поддерживает различные [http://www.jooq.org/doc/3.7/manual/sql-execution/fetching/ способы] получения результатов запросов (Record или смапленные).
 +
 
 +
Минусы:
 +
* Трудно/криво расширяются сгенерированные классы записей (трудно добавлять в них доменную логику).
 +
* Для работы с Oracle нужна платная лицензия — не очень критично, так как для открытых СУБД (MySQL, PostgreSQL и так далее) доступна версия под лицензией Apache 2.0, разрешающей коммерческое использование.
 +
 
 +
Краткий отзыв — см. например http://teonos.com/blog/java/development/2014/11/10/experiences-with-jOOQ.html
  
 
== [http://javalite.io/activejdbc ActiveJDBC] ==
 
== [http://javalite.io/activejdbc ActiveJDBC] ==
Строка 33: Строка 58:
 
== [http://ebean-orm.github.io/ Ebean ORM] ==
 
== [http://ebean-orm.github.io/ Ebean ORM] ==
  
По большей части похож на JPA, те же яйца, только в профиль. Классы размечаются ровно теми же JPA-аннотациями… EbeanServer — тот же аналог сессии или persistence manager’а… других частей JPA, правда, нет.
+
По большей части похож на JPA, те же яйца, только в профиль. Классы размечаются ровно теми же JPA-аннотациями… EbeanServer — тот же аналог сессии или persistence manager’а…
  
 
Плюсы:
 
Плюсы:
Строка 41: Строка 66:
 
Минусы:
 
Минусы:
 
* Серьёзные минусы вроде отсутствуют, разве что логика отображения та же, что в JPA
 
* Серьёзные минусы вроде отсутствуют, разве что логика отображения та же, что в JPA
 +
 +
== Идея (велосипедик) — PHP-like ORM ==
 +
 +
Описанное примерно соответствует либо jOOQ, либо Querydsl с дополнительно прикрученной улучшенной логикой Active Record.
 +
 +
* Объект «соединение». Умеет делать запросы в синтаксически кратком стиле (возможно, Fluent API) и возвращать записи в виде чего-то типа Map<String,Object>. Кроме того, является аналогом сессии/persistence manager’а для моделей.
 +
* Базовый класс модели хранит запись, полученную из БД, в виде такого же объекта Map, не раскладывая её по своим полям. Благодаря этому создание модели максимально легковесно — это просто вызов конструктора, который делает 1 действие — сохраняет к себе этот Map.
 +
* Все вычислимые значения — например, загружаемые ассоциации — хранятся в ещё одном Map’е. Есть общие геттер и сеттер, работающие по названию поля и возвращающие, кэширующие и вычисляющие дополнительные значения.
 +
* В модели есть ссылка на «грязную»/«чистую» копию и флаг, какой является текущая. Как только кто-то начинает модифицировать модель — объект создаёт свою копию, а сам становится «грязным».
 +
* Логика сохранения в БД также живёт в модели, в виде одного метода типа save(), или, возможно, saveAll(), если в основу класть массовые операции. Это похоже на стиль ActiveRecord, с той только разницей, что в модель всё-таки нужно передавать объект «соединение».
 +
* В модели есть ссылка на resultset, частью которого она является — это позволяет подгружать связи массово.
 +
* Круче всего, если класс модели не абстрактный и позволяет с собой работать вообще без создания дочерних классов.

Текущая версия на 11:12, 19 февраля 2016

JPA: Hibernate, EclipseLink

Плюсы:

  • Наиболее «каноничный» Java ORM
  • Есть дополнительные фичи — например, в Hibernate есть Envers, из коробки умеющий логгировать историю изменений сущностей в отдельные таблицы

Минусы:

  • Код не лаконичен. Нужно задавать маппинги, классы сущностей, конструировать запросы либо через строковой HQL/JPQL, либо через многословный Criteria…
  • Трудно использовать для динамических сущностей (объектов произвольной структуры) — так или иначе нужно конфигурировать маппинг, даже если используется динамическое отображение без классов моделей.
  • Возможно, не вполне идеальна логика отображения — конструирование объекта всегда связано с десериализацией, для сохранения ID связанных объектов без самих объектов применяются proxy-классы и ленивая подгрузка (нет возможности одно и то же поле, скажем, person_id, видеть и в виде ID, и в виде объекта)…
  • HQL/JPQL — всё-таки недоразумение. Не могу понять смысл реализации собственного строкового языка запросов — SQL если уж во что-то заворачивать, то во что-то объектно-структурированное — хотя бы в объект типа «запрос» с полями tables, where, order by, group by и т. п., но не снова в строковой же литерал! Кроме того, к нему есть различные претензии.

ActiveJPA

Попытка реализации Active Record поверх JPA.

Минусы:

  • Велосипедик.

Querydsl

Типобезопасное (импортирующее схему в Java классы) Fluent API построения SQL-запросов.

Плюсы:

  • API построения запросов довольно удобное.
  • Универсальный, работает как с JPA, так и с голым SQL.

Минусы:

  • Хоть и может возвращать DTO’шки (кроме обычного Tuple), они не является ActiveRecord’ами, то есть никакой логики их обновления или подгрузки связей нет. То есть, скорее должен рассматриваться как дополнение к мапперу.

jOOQ

Плюсы:

  • Легковесный Fluent API + Active Record фреймворк.
  • Похож на Querydsl, тоже использует кодогенерацию и типобезопасные запросы через Fluent API, однако в дополнение к этому генерирует классы моделей (Active Record) и поддерживает различные способы получения результатов запросов (Record или смапленные).

Минусы:

  • Трудно/криво расширяются сгенерированные классы записей (трудно добавлять в них доменную логику).
  • Для работы с Oracle нужна платная лицензия — не очень критично, так как для открытых СУБД (MySQL, PostgreSQL и так далее) доступна версия под лицензией Apache 2.0, разрешающей коммерческое использование.

Краткий отзыв — см. например http://teonos.com/blog/java/development/2014/11/10/experiences-with-jOOQ.html

ActiveJDBC

Плюсы:

  • Active Record для Java
  • Легковесный:
    • Необязательны геттеры/сеттеры, поля можно читать по именам model.get("поле")
    • Нет ни проксей, ни сессий, ни persistence manager’ов, ни DAO, ни репозиториев, ни «attach/detach», ни собственного языка запросов

Минусы:

  • Неотключаемое автоматическое определение таблиц и типов полей во время выполнения. Также есть автоматическая привязка классов к таблицам по правилам английского языка — извращение, но по крайней мере отключаемое.
  • Отсутствие поддержки нескольких схем (#144).
  • Трудно во время выполнения явно указать соединение БД, с которым должна работать конкретная модель — несколько соединений указывается только на уровне аннотаций во время компиляции, а в рантайме всегда используется текущее «привязанное» к имени соединение.
  • Отсутствие доступа к «старым» («чистым») значениям полей при сохранении модели.
  • Отсутствие поддержки композитных первичных ключей — всегда нужна автоинкрементная колонка «id», даже в таблицах отношений «многие ко многим»

Ebean ORM

По большей части похож на JPA, те же яйца, только в профиль. Классы размечаются ровно теми же JPA-аннотациями… EbeanServer — тот же аналог сессии или persistence manager’а…

Плюсы:

  • Наличие Fluent API запросов, отсутствие велосипедных языков типа JPQL
  • Встроенная поддержка сериализации/десериализации JSON

Минусы:

  • Серьёзные минусы вроде отсутствуют, разве что логика отображения та же, что в JPA

Идея (велосипедик) — PHP-like ORM

Описанное примерно соответствует либо jOOQ, либо Querydsl с дополнительно прикрученной улучшенной логикой Active Record.

  • Объект «соединение». Умеет делать запросы в синтаксически кратком стиле (возможно, Fluent API) и возвращать записи в виде чего-то типа Map<String,Object>. Кроме того, является аналогом сессии/persistence manager’а для моделей.
  • Базовый класс модели хранит запись, полученную из БД, в виде такого же объекта Map, не раскладывая её по своим полям. Благодаря этому создание модели максимально легковесно — это просто вызов конструктора, который делает 1 действие — сохраняет к себе этот Map.
  • Все вычислимые значения — например, загружаемые ассоциации — хранятся в ещё одном Map’е. Есть общие геттер и сеттер, работающие по названию поля и возвращающие, кэширующие и вычисляющие дополнительные значения.
  • В модели есть ссылка на «грязную»/«чистую» копию и флаг, какой является текущая. Как только кто-то начинает модифицировать модель — объект создаёт свою копию, а сам становится «грязным».
  • Логика сохранения в БД также живёт в модели, в виде одного метода типа save(), или, возможно, saveAll(), если в основу класть массовые операции. Это похоже на стиль ActiveRecord, с той только разницей, что в модель всё-таки нужно передавать объект «соединение».
  • В модели есть ссылка на resultset, частью которого она является — это позволяет подгружать связи массово.
  • Круче всего, если класс модели не абстрактный и позволяет с собой работать вообще без создания дочерних классов.