Comments 25
JOOQ классная библиотека. Пользовался в одном из проектов. Из минусов наверное только то что он платный для платных баз данных.
Хибернейт никогда не понимал и мне он всегда казался чем то лишним, но это дело вкуса.
Кстати помню в Java в с использованием JOOQ иногда сильно увеличивалось время компиляции, в 11 вроде пофиксили.
Просто не надо включать автоматическую кодогенерацию.
Схема БД меняется сравнительно редко и кодогенерацию лучше запускать вручную по мере необходимости.
Но если мы не хотим мараться об SQL, нам будет приятно видеть что-то вроде:
return dsl.selectFrom(COUNTRIES)
.where(COUNTRIES.POPULATION.greaterThan(amount))
.fetch();
Коллеги, а это действительно много приятнее и чище, чем
SELECT * FROM COUNTRIES WHERE POPULATION>:amount
???
ОК, я понимаю, когда двоичный код
BB 11 01 B9 0D 00 B4 0E 8A 07 43 CD 10 E2 F9 CD 20 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21
сворачивается в
console.log("Hello World");
но тут-то по структуре остаётся тот же самый SQL, о который мы хотели "не испачкаться", да ещё и букв больше!
Я не понимаю, почему SQL — это "мараться"?
По поводу других аллегорий, применяемых в статье, тоже можете смело обращаться ко мне. Объясню.
Почему "SQL" = "фекалии"? Или что вы подразумеваете под фекалиями, если это не SQL?
В таком случае я остаюсь в недоумении, с чего вы взяли, что вы способны объяснить смыслы, которые вы вложили в эту статью:
По поводу других аллегорий, применяемых в статье, тоже можете смело обращаться ко мне. Объясню.
И, кстати, спасибо за минус. Вы подтвердили моё мнение о Вас.
Вот теперь — пожалуйста. Я обычно не ставлю минуса просто потому, что мне что-то не понравилось. Я могу просто что-то неправильно понять. Но в данном случае у вас была возможность объяснить свою позицию, которой вы не воспользовались. Первый минус не от меня прилетел, но вы тоже подтвердили моё мнение о вас. Рад, что мы с вами не разочаровали друг друга.
Я не понимаю, почему SQL — это "мараться"?
Потому что культ карго, и для чего нужны сущности и репозитории автор статьи явно не понимает.
SQL не мараться, я придумываю запрос в SQL а потом имплементирую его в Criteria API. Думаю это справедливо для большинства, все таки исходить приходится от БД.
Но ОРМ фреймворки многоe автоматизируют, например маппинг результата в объекты, И параметров запроса в запрос, динамические запросы (например разные условия - фильтрация по разным параметрам, разные сортировки), менеджмент транзакций, обновления данных и еще много чего.
К сожалению такие масштабные абстракции накладывают необходимость изучать как это работает, не согласен что в JPA легко начать, только если совсем hello world, но в реальном мире легче начать как раз с JDBC, а c JPA сразу упираешься в незнание и приходится разбираться в этой магии. Но оно того стоит ИМХО.
вот только этот хибер и ему подобное — использование sql на 5% от всех возможностей субд
Поэтому на чтение можно писать сырой SQL, это просто.
А ORM годится для записи — т.к. для записи нам как раз нужны наши сущности с логикой, которые будут контролировать свои инварианты, все чуть сложнее, т.к. нужно определять что в модели поменялось, плюс изоляция БЛ от работы с базой(если, конечно, уйти от мысли что сущность это табличка в БД, и воспринимать хранилище как деталь, а иначе, конечно, пользу тяжёлых ORM не понять).
Имхо, ничего лучше jdbc и jdbi для работы с sql для java не придумали
Есть следующая постановка задачи. Нужно при сборке сгенерировать сущности и всё что там jooq генерирует, но базу нужно поднять в процессе сборки перед генерацией и после генерации завершить ее работу. Желательно поднять PostgreSQL как на продакшене, а не H2. Может кто-то предложить рабочую maven конфигурацию?
Рабочая конфигурация при этом не сильно будет отличаться от предложенной в посте (Postgres меняем на Embeded — вот и все отличия).
Понятно, что статья старая, но добавлю свои 5 копеек, а то может сложиться превратное впечатление о Jooq.
Прежде всего, все примеры из статьи имеют место быть, но я бы по другому делал.
Например, получение строки таблицы по id (мне больше нравится название переменной db, а не dsl):
val user = db.fetchOne(USERS, USERS.ID.eq(userId), USERS.DELETED_AT.isNull)
Или создание записи:
val user = db.newRecord(USERS.class)
user.setName("Name")
user.store()
Это уже выглядит получше, чем примеры из статьи.
При этом логику дозагрузки списков нужно писать. И в том же хибернейте довольно много проблем с ней (делать ее LAZY or EAGER и как в разных местах это чередовать). Здесь же явно задаешь что нужно. Jooq-мэперы не использую, просто прохожу циклом в нужном методе, так как так все компактно видно в одном месте. Вместе с Jooq применяю Dao (Data Access Object) классы, которые включают всю сколько-нибудь нетривиальную логику получения данных. При этом классы с отчетами обычно не используют DAO, т.к. это один или несколько сложных sql-запросов сами по себе.
В целом, Jooq как раз для любителей чистого SQL. Просто языки программирования не могут типизировать SQL внутри строк, поэтому типизация достигается через такой DSL.
Генератор запускаю вручную и комичу сгененированный код в систему контроля версий. Так пока что проще и никаких проблем с таким подходом.
JOOQ и его кроличья нора. Как выжить без Hibernate