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

Jooq vs Hibernate 4.0

Я читал много версий этого холивара, и все-таки решил написать свой. Буду рад комментариям, буду их учитывать и редактировать статью далее... так как ответить на такой сложный вопрос не так-то просто.

Что мы сравниваем? ORM. Object relational mapping - технология, которая позволяет абстрагироваться от базы данных, оперируя объектами в коде.

  1. Могут ли jooq и Hibernate служить абстракцией над базой данных? Определенно да. Как это проверить? Оба фреймворка генерируют sql и разработчику необязательно писать sql запросы в коде.

  2. Sql injection defense. тоже есть у обоих, избитая тема, не буду раскрывать. (Возможность избежать конкатенации в нативных sql запросах имеется и там и там.)

  3. Connection pool. Присутствует в обоих фреймворках.

  4. Static typification/Compile-time check. Тоже есть у обоих. У jooq она лучше потому что интерфейс более гибкий и покрывает намного больше кейсов чем hibernate.

  5. One-to-many, Many-to-one implementation. Есть и там и там с небольшой оговоркой: проблема "n+1". Можно ли ее как-то избежать? в Hibernate придется писать разные реализации для запросов на чтение. В Jooq это тоже нужно делать, но другим более легким путем. В jooq есть multiset

    fun fetchPersonbyId(
            personId: UUID
        ): PersonApiEntity {
            return dslContext.select(
                person.ID,
                person.NAME,
                DSL.multiset(
                    dslContext.select(
                        country.asterisk()
                    )
                        .from(COUNTRY)
                        .where(COUNTRY.PERSON_ID.eq(person.ID).and(COUNTRY.FORBIDDEN.eq(true)))
                ).`as`("prohibitedCountries")
                    .convertFrom { prohibitedCountries -> prohibitedCountries.map { it.toCountryApiEntity() } },
                DSL.multiset(
                    dslContext.select(country.asterisk())
                        .from(COUNTRY)
                        .where(COUNTRY.PERSON_ID.eq(person.ID).eq(person.ID)).and(COUNTRY.OCEAN.eq(true)))
                ).`as`("oceanCountries")
                    .convertFrom { oceanCountries -> oceanCountries.map { it.toCountryApiEntity()}})
                .from(person)
                .where(person.ID.eq(personId))
                .fetchOne { it.personApiEntity() }
                ?: throw NotFoundException("Not found person with id: $personId")
        }                                                          
    

С помощью этой фичи можно писать разные запросы при этом модели данных остаются без изменений.

Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.