Рубрики
Без рубрики

Многострочные строковые литералы с текстовыми блоками Java

Узнайте, что такое текстовые блоки Java и как их можно использовать для повышения удобочитаемости JPQL, SQL-запросов или строковых значений JSON.

Автор оригинала: Vlad Mihalcea.

Вступление

В этой статье показано, как новые текстовые блоки Java могут помочь повысить читаемость JPQL, SQL-запросов или строковых значений JSON.

Еще в 2005 году я разрабатывал проект .NET, и мне очень понравилась функция C# Дословного строкового литерала , поскольку она позволяет писать многострочное строковое значение без необходимости связывать каждую отдельную строку.

Функция текстовых блоков Java 13 теперь предоставляет возможность создания многострочных значений Java String .

Посмотрите, как новые текстовые блоки #Java могут помочь вам повысить читаемость JPQL, SQL-запросов или строковых значений JSON. https://t.co/wBKLIyb0XF pic.twitter.com/H6VOKW4szH

Текстовые блоки Java для запросов JPQL или SQL

Независимо от того, выполняете ли вы JPQL или SQL-запрос без текстовых блоков, именно так будет выглядеть выполнение запроса при использовании JPA:

List posts = entityManager
.createNativeQuery(
    "SELECT *\n" +
    "FROM (\n" +
    "    SELECT *,\n" +
    "           dense_rank() OVER (\n" +
    "               ORDER BY \"p.created_on\", \"p.id\"\n" +
    "           ) rank\n" +
    "    FROM (\n" +
    "        SELECT p.id AS \"p.id\",\n" +
    "               p.created_on AS \"p.created_on\",\n" +
    "               p.title AS \"p.title\",\n" +
    "               pc.id as \"pc.id\",\n" +
    "               pc.created_on AS \"pc.created_on\",\n" +
    "               pc.review AS \"pc.review\",\n" +
    "               pc.post_id AS \"pc.post_id\"\n" +
    "        FROM post p\n" +
    "        LEFT JOIN post_comment pc ON p.id = pc.post_id\n" +
    "        WHERE p.title LIKE :titlePattern\n" +
    "        ORDER BY p.created_on\n" +
    "    ) p_pc\n" +
    ") p_pc_r\n" +
    "WHERE p_pc_r.rank <= :rank\n",
    Tuple.class)
.setParameter("titlePattern", "High-Performance Java Persistence %")
.setParameter("rank", 5)
.getResultList();

Для удобства чтения мы не хотим отображать весь запрос в одной строке, поэтому нам нужно использовать многострочную Строку . До Java 13 вы либо использовали бы String конкатенацию, либо StringBuilder для создания многострочной Строки .

Начиная с Java 13, вы можете использовать текстовые блоки, и вам даже не нужно вручную преобразовывать устаревшую многострочную Строку конкатенацию в новый формат многострочных текстовых блоков. С помощью IntelliJ IDEA вы можете нажать ALT + ENTER и выбрать опцию Заменить текстовым блоком :

После применения действия Заменить текстовым блоком вот как может выглядеть ваш запрос:

List posts = entityManager
.createNativeQuery("""
    SELECT *
    FROM (
        SELECT *,
               dense_rank() OVER (
                   ORDER BY "p.created_on", "p.id"
               ) rank
        FROM (
            SELECT p.id AS "p.id",
                   p.created_on AS "p.created_on",
                   p.title AS "p.title",
                   pc.id as "pc.id",
                   pc.created_on AS "pc.created_on",
                   pc.review AS "pc.review",
                   pc.post_id AS "pc.post_id"
            FROM post p
            LEFT JOIN post_comment pc ON p.id = pc.post_id
            WHERE p.title LIKE :titlePattern
            ORDER BY p.created_on
        ) p_pc
    ) p_pc_r
    WHERE p_pc_r.rank <= :rank
    """,
    Tuple.class)
.setParameter("titlePattern", "High-Performance Java Persistence %")
.setParameter("rank", 5)
.getResultList();

SQL – запрос намного более удобочитаем при использовании текстовых блоков Java.

Текстовые блоки Java для объектов JSON

Еще одно место, где текстовые блоки Java действительно полезны, – это когда вам нужно представить JSON, XML или HTML в вашем Java-коде.

Рассмотрим следующую Книгу сущность, имеющую атрибут JSON свойства :

entityManager.persist(
    new Book()
    .setId(1L)
    .setIsbn("978-9730228236")
    .setProperties(
        "{" +
        "   \"title\": \"High-Performance Java Persistence\"," +
        "   \"author\": \"Vlad Mihalcea\"," +
        "   \"publisher\": \"Amazon\"," +
        "   \"price\": 44.99," +
        "   \"reviews\": [" +
        "       {" +
        "           \"reviewer\": \"Cristiano\", " +
        "           \"review\": \"Excellent book to understand Java Persistence\", " +
        "           \"date\": \"2017-11-14\", " +
        "           \"rating\": 5" +
        "       }," +
        "       {" +
        "           \"reviewer\": \"T.W\", " +
        "           \"review\": \"The best JPA ORM book out there\", " +
        "           \"date\": \"2019-01-27\", " +
        "           \"rating\": 5" +
        "       }," +
        "       {" +
        "           \"reviewer\": \"Shaikh\", " +
        "           \"review\": \"The most informative book\", " +
        "           \"date\": \"2016-12-24\", " +
        "           \"rating\": 4" +
        "       }" +
        "   ]" +
        "}"
    )
);

При преобразовании атрибута properties в текстовый блок объект JSON, несомненно, становится гораздо более читабельным:

entityManager.persist(
    new Book()
    .setId(1L)
    .setIsbn("978-9730228236")
    .setProperties("""
        {
           "title": "High-Performance Java Persistence",
           "author": "Vlad Mihalcea",
           "publisher": "Amazon",
           "price": 44.99,
           "reviews": [
               {
                   "reviewer": "Cristiano",
                   "review": "Excellent book to understand Java Persistence",
                   "date": "2017-11-14",
                   "rating": 5
               },
               {
                   "reviewer": "T.W",
                   "review": "The best JPA ORM book out there",
                   "date": "2019-01-27",
                   "rating": 5
               },
               {
                   "reviewer": "Shaikh",
                   "review": "The most informative book",
                   "date": "2016-12-24",
                   "rating": 4
               }
           ]
        }
        """
    )
);

Круто, правда?

Вывод

Наконец, в Java есть правильное решение для многострочных строковых значений. Я переключил свой Высокопроизводительный репозиторий Java на GitHub , а также учебные материалы для семинара по высокопроизводительному SQL , и результаты впечатляют.

Учитывая, что Java 13, 14, 15 и 16 не являются выпусками LTS (долгосрочной поддержки), большинство проектов Java, вероятно, будут ждать, пока Java 17 начнет внедрять эту функцию. Но для нового проекта, который будет запущен в производство после сентября 2021 года, когда предполагается выпустить Java 17, было бы неплохо начать разработку с использованием Java 14.