Статьи

Использование Oracle AQ в Java не станет легче, чем это

Как недавно было объявлено в нашей новостной рассылке , грядущая версия jOOQ 3.5 будет включать в себя потрясающую новую функцию для тех из вас, кто использует базу данных Oracle: встроенная поддержка Oracle AQ! И ваш клиентский код будет так легко написать, что вы сразу же разместите эти AQ по всей базе данных.

Как это работает?

обоснование JOOQ

Главная причина, по которой многие из наших пользователей любят jOOQ, — это наш генератор кода. Он генерирует Java-представление вашей схемы базы данных со всеми соответствующими объектами, которые вам нужны при написании SQL. До сих пор это включало таблицы, последовательности, пользовательские типы, пакеты, процедуры.

Новым является то, что объекты AQ теперь также генерируются и ассоциируются с сгенерированным типом объекта.

Простая схема

Давайте рассмотрим написание этой простой схемы ( все источники доступны на GitHub )

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
CREATE OR REPLACE TYPE book_t
  AS OBJECT (
  ID         NUMBER(7),
  title      VARCHAR2(100 CHAR),
  language   VARCHAR2(2 CHAR)
)
/
 
CREATE OR REPLACE TYPE books_t
  AS VARRAY(32) OF book_t
/
 
CREATE OR REPLACE TYPE author_t
  AS OBJECT (
  ID         NUMBER(7),
  first_name VARCHAR2(100 CHAR),
  last_name  VARCHAR2(100 CHAR),
  books      books_t
)
/
 
CREATE OR REPLACE TYPE authors_t
  AS VARRAY(32) OF author_t
/
 
BEGIN
  DBMS_AQADM.CREATE_QUEUE_TABLE(
    queue_table => 'new_author_aq_t',
    queue_payload_type => 'author_t'
  );
 
  DBMS_AQADM.CREATE_QUEUE(
    queue_name => 'new_author_aq',
    queue_table => 'new_author_aq_t'
  );
 
  DBMS_AQADM.START_QUEUE(
    queue_name => 'new_author_aq'
  );
  COMMIT;
END;
/

Итак, по сути, у нас есть как OBJECT, так и VARRAY для книг и авторов. Вы можете предпочесть использование типов TABLE, а не типов VARRAY, но ради простоты мы придерживаемся VARRAY (поскольку в Oracle не так просто использовать вложенные типы TABLE с AQ в AQ).

Мы также создали очередь, которая уведомляет слушателей каждый раз, когда новый автор добавляется в базу данных — вместе с их книгами. Представьте, что операции постановки в очередь выполняются в триггере либо для автора, либо для таблицы книг.

сгенерированный jOOQ код

Когда вы запустите генератор кода jOOQ (версия 3.5 и выше) для вышеуказанной схемы, вы получите новый файл Queues.java , который содержит:

1
2
3
4
5
public class Queues {
    public static final Queue<AuthorT> NEW_AUTHOR_AQ
      = new QueueImpl<AuthorT>(
         "NEW_AUTHOR_AQ", SP, AUTHOR_T);
}

Очевидно, что ранее показанные типы OBJECT и VARRAY также генерируются jOOQ, как lables.

(конечно, фактические шаблоны именования для сгенерированного кода Java полностью настраиваются )

Использование созданных артефактов

Приведенный выше код не очень хорошо отформатирован в этом блоге, но вы не видите ничего этого в своей повседневной работе. Потому что, когда вы хотите поместить сообщение в эту очередь, вы можете просто написать:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
// Create a new OBJECT type with nested
// VARRAY type
AuthorT author = new AuthorT(
    1,
    "George",
    "Orwell",
    new BooksT(
        new BookT(1, "1984", "en"),
        new BookT(2, "Animal Farm", "en")
    )
);
 
// ... and simply enqueue that on NEW_AUTHOR_AQ
DBMS_AQ.enqueue(configuration, NEW_AUTHOR_AQ, author);

Шутки в сторону? Это просто? Да!

Сравните вышесказанное с тем, что вы написали ранее через JDBC или с помощью собственных API-интерфейсов Oracle. Вы найдете пару примеров о том, как сериализовать / десериализовать типы RAW, но, честно говоря, очереди потрясающие, потому что вы можете отправлять типы OBJECT через базу данных, а мы не видим этих примеров из Oracle. На самом деле, поверьте нам, вы не хотите сериализовать типы OBJECT, VARRAY или TABLE через JDBC. Вы не Это наша работа. Мы взломали JDBC, так что вам не нужно .

Конечно, вы также можете передавать MESSAGE_PROPERTIES_T , ENQUEUE_OPTIONS_T и DEQUEUE_OPTIONS_T качестве аргументов в enqueue() и dequeue() .

Снятие очереди так же просто. Следующие вызовы сгенерируют блокирующий вызов и будут ждать следующего сообщения AUTHOR_T:

1
2
AuthorT author =
  DBMS_AQ.dequeue(configuration, NEW_AUTHOR_AQ);

Вот и все. Не может быть так сложно, не так ли?

jooq-The-лучший способ к записи-SQL-в-Java-маленький

Goodie: Java 8 и Oracle AQ

С помощью приведенного выше простого API и Java 8 мы можем сделать то, что Oracle, должно быть, знал давно, когда они переименовали маркетинговое имя Oracle AQ в Oracle Streams. Давайте создадим поток Java 8 для объектов OBJECT, созданных AQ, с помощью jOOQ. Проще простого. Просто пиши:

1
2
3
4
5
6
7
8
static <R extends UDTRecord<R>> Stream<R> stream(
    Configuration c,
    Queue<R> queue
) {
    return Stream.generate(() ->
        DBMS_AQ.dequeue(c, queue)
    );
}

А теперь используйте эту красоту вот так:

1
2
3
4
5
6
7
stream(configuration, NEW_AUTHOR_AQ)
    .limit(10)
    .forEach(author -> {
        System.out.println(
            author.getFirstName() + " " +
            author.getLastName());
    });

Вышеприведенный оператор берет следующие 10 сообщений, снятых таким образом, и выводит их на консоль.

Ссылка: Использование Oracle AQ в Java не станет легче, чем это, от нашего партнера по JCG Лукаса Эдера из блога JAVA, SQL и JOOQ .