Статьи

Руководство для начинающих по использованию Java EE с jOOQ

Java EE поставляется с собственным API персистентности: JPA. JPA наиболее эффективен, когда вы хотите отобразить ваши сущности СУБД (таблицы / отношения) на сущности (классы) Java, в основном следуя стратегии отображения 1: 1. Идея этого заключается в том, что часто бизнес-логика на самом деле не ориентирована на наборы, как реляционная алгебра или SQL, а ориентирована на записи, что означает, что бизнес-правила и бизнес-логика применяются к отдельным записям.

Другими словами, когда SQL и реляционная алгебра — это значения (кортежи), JPA — это идентичность и состояние (отдельных записей). И здесь сияет JPA, потому что:

Жизнь слишком коротка, чтобы писать CRUD с SQL

Но, как всегда говорил Гэвин Кинг:

Gavin-король-на-спящий режим

RDBMS — это не только CRUD

Гэвин Кинг хорошо знал об ажиотаже OLAP, который происходил в то время, когда он начал работать над Hibernate , самой популярной реализацией JPA. Бизнес-аналитика, или наука о данных, как ее называют в настоящее время, опирается на гораздо более продвинутые функциональные возможности, чем простые CRUD-функциональные возможности, которые никогда не предназначались ни для спецификации JPA, ни для ее реализаций.

На самом деле вам не обязательно использовать OLAP, чтобы извлечь выгоду из собственного SQL, также могут появиться и более простые варианты использования в более обычных средах OLTP, таких как

  • Составление отчетов
  • Пакетная и массовая обработка данных
  • Запрос со сложными бизнес-правилами

Хотя JPA предлагает JPQL и Criteria API, которые помогут вам выразить некоторую сложность в ваших запросах, вы в конечном итоге будете ограничены функциями, предлагаемыми в этих языках и API, поскольку Майкл Саймонс недавно задокументировал интересный Criteria API для сравнения с jOOQ. ,

По этой причине все реализации JPA предлагают способ запроса базы данных с использованием «собственного SQL» . В предыдущем сообщении в блоге мы показали, как вы можете использовать безопасный DSL API jOOQ для запуска запросов SQL через собственный API запросов JPA , а затем получать результаты…

  • … как управляемые объекты
  • … Как DTO, сопоставленные с использованием SqlResultSetMapping

В вышеупомянутых случаях jOOQ используется только как построитель SQL-запросов , а выполнение запросов оставлено на усмотрение JPA.

Выполнять все запросы к базе данных с помощью jOOQ, в Java EE

Помните философию jOOQ :

JOOQ — это, по сути, безопасный тип JDBC. Больше ничего.

Даже если вы можете использовать JPA для выполнения нативного SQL, это не обязательно. Вы можете работать непосредственно на уровне JDBC, что часто требуется с JPA, например, при работе…

  • … С типами данных, зависящими от поставщика
  • … С нетривиальными хранимыми процедурами
  • … с заявлением партии
  • … С обновляемыми курсорами

Когда вы запускаете свое приложение на сервере приложений, вы можете выбрать те функции, которые вам нужны и которые вам нужны, и использовать проприетарные API (например, jOOQ, который работает поверх JDBC) для остальных. Например, вы можете использовать:

  • EJB для управления сессиями и областями действия
  • CDI для внедрения зависимости
  • JOOQ для взаимодействия с вашей базой данных

(Вы также можете добавить JTA в стек — по соображениям простоты мы пока пропустим это)

Процедура проста: просто внедрите javax.sql.DataSource в ваш сессионный компонент, используя CDI:

1
2
3
4
5
6
@Stateless
public class LibraryEJB {
 
    @Resource(lookup="java:data-source-configuration")
    private DataSource ds;
}

… и начать работать с ним, используя JDBC:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
public List<Author> fetchAuthors()
throws SQLException {
    List<Author> result = new ArrayList<>();
 
    // Get a Connection from the injected DataSource
    try(Connection con = ds.getConnection();
        PreparedStatement stmt = con.prepareStatement(
            "SELECT * FROM AUTHOR ORDER BY ID");
        ResultSet rs = stmt.executeQuery()
    ) {
        result.add(new Author(
            rs.getInt("ID"),
            rs.getString("FIRST_NAME"),
            rs.getString("LAST_NAME")
        ));
    }
 
    return result;
}

… или используя jOOQ:

1
2
3
4
5
6
7
8
public Result<AuthorRecord> fetchAuthors() {
 
    // Pass the injected DataSource to jOOQ
    return DSL.using(ds, H2)
              .selectFrom(AUTHOR)
              .orderBy(AUTHOR.ID)
              .fetch();
}

Обратите внимание, что jOOQ — по умолчанию — с нетерпением извлекает все результаты в память , с нетерпением закрывая ресурсы, такие как JDBC Connection , PreparedStatement и ResultSet , так что вам не нужно самостоятельно справляться с трудностями управления ресурсами.

Еще раз:

JOOQ — это, по сути, безопасный тип JDBC. Больше ничего.

JDBC всегда был важной частью приложений Java EE по самым разным причинам, включая доступ к функциям конкретного поставщика. JOOQ добавляет безопасность типа времени компиляции поверх JDBC. Больше ничего. Все, что работает с JDBC, будет работать с jOOQ.

В частности, jOOQ никогда не будет мешать вашей транзакции или модели сеанса, независимо от вашего выбора. Все, что нужно jOOQ — это Connection JDBC или источник данных.

Выполнение примера в JBoss WildFly

Приведенный выше пример можно извлечь из GitHub и запустить, например, непосредственно в WildFly — или с небольшими изменениями на любом другом сервере приложений Java EE: https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples / jOOQ-JavaEE-пример

Пример был создан для WildFly в контексте вебинара с Аруном Гуптой. Вебинар отвечает на следующие вопросы:

  • Что такое JOOQ?
  • Почему JOOQ, когда есть JDBC и JPA?
  • Как это согласуется с приложениями Java EE? Использует ли он базовый поставщик сохраняемости JPA или какое-либо другое соединение?
  • Плюсы / минусы по JPA? Чистый спящий?
  • Насколько хорошо это масштабируется?
  • Показать пример кода в приложении Java EE
  • jOOQ для CRUD или доменных приложений?
  • Как в конечном итоге всю работу в jOOQ можно интегрировать в JPA и стандартизировать? Или это будет больше JDBC?

Полный вебинар можно увидеть на YouTube, здесь: