Pull to refresh

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 преимущество что его можно скопировать, выполнить и проверить результат или посмотреть план выполнения. А так выглядят одинаково. Возможно раньше IDE подсказывала в первом случае лучше, хотя сейчас и обычный SQL хорошо дополняется в IntelliJ
и даже валидируется при компиляции, что позволяет избежать рантайм ошибок, ради которых и мутится все эти dsl на java)

SQL не мараться, я придумываю запрос в SQL а потом имплементирую его в Criteria API. Думаю это справедливо для большинства, все таки исходить приходится от БД.

Но ОРМ фреймворки многоe автоматизируют, например маппинг результата в объекты, И параметров запроса в запрос, динамические запросы (например разные условия - фильтрация по разным параметрам, разные сортировки), менеджмент транзакций, обновления данных и еще много чего.

К сожалению такие масштабные абстракции накладывают необходимость изучать как это работает, не согласен что в JPA легко начать, только если совсем hello world, но в реальном мире легче начать как раз с JDBC, а c JPA сразу упираешься в незнание и приходится разбираться в этой магии. Но оно того стоит ИМХО.

вот только этот хибер и ему подобное — использование sql на 5% от всех возможностей субд. и все либы возвращают лист из результсета, когда данные можно использовать напрямую из самого результсета. т.е. добавляется одна лишняя операция. ну и когда это работает на десктопе — это терпимо, а вот когда это серверное приложение и все эти объекты строятся для кучи пользователей — и памяти мало и времени уходит попусту много.
вот только этот хибер и ему подобное — использование sql на 5% от всех возможностей субд

Поэтому на чтение можно писать сырой SQL, это просто.
А ORM годится для записи — т.к. для записи нам как раз нужны наши сущности с логикой, которые будут контролировать свои инварианты, все чуть сложнее, т.к. нужно определять что в модели поменялось, плюс изоляция БЛ от работы с базой(если, конечно, уйти от мысли что сущность это табличка в БД, и воспринимать хранилище как деталь, а иначе, конечно, пользу тяжёлых ORM не понять).

UFO just landed and posted this here
Согласен. Поменял имя поля — и привет, запрос не работает.

Имхо, ничего лучше jdbc и jdbi для работы с sql для java не придумали

Есть следующая постановка задачи. Нужно при сборке сгенерировать сущности и всё что там jooq генерирует, но базу нужно поднять в процессе сборки перед генерацией и после генерации завершить ее работу. Желательно поднять PostgreSQL как на продакшене, а не H2. Может кто-то предложить рабочую maven конфигурацию?

Вам, похоже, нужен Embeded Postgres + java-генератор, описанный в статье (через ApplicationListener). В таком случае, при сборке сначала отработает Embeded Postgres, поднимет Вам базу, потом отработает flyway и накатит таблицы, а потом сработает генератор, который сгенерирует сущности. При остановке приложения база будет свёрнута.

Рабочая конфигурация при этом не сильно будет отличаться от предложенной в посте (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.

Генератор запускаю вручную и комичу сгененированный код в систему контроля версий. Так пока что проще и никаких проблем с таким подходом.

Sign up to leave a comment.

Articles