Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Запросы в репозиториях

Методов CrudRepository хватает для работы с одной записью по id. Для поиска нужны свои запросы. В Micronaut Data их чаще всего не пишут, а называют: имя метода findByTitleContains обработчик разбирает при компиляции и превращает в SQL с WHERE title LIKE. Ошибка в имени поля обнаружится сразу при сборке, а не у пользователя.

Запросы по имени метода

Дополните репозиторий статей:

// src/main/java/com/example/ArticleRepository.java
package com.example;
 
import io.micronaut.data.annotation.Query;
import io.micronaut.data.jdbc.annotation.JdbcRepository;
import io.micronaut.data.model.query.builder.sql.Dialect;
import io.micronaut.data.repository.PageableRepository;
 
import java.util.List;
 
@JdbcRepository(dialect = Dialect.H2)
public interface ArticleRepository extends PageableRepository<Article, Long> {
 
    List<Article> findByTitleContains(String text);
 
    List<Article> findByTitleContainsOrderByIdDesc(String text);
 
    long countByTitleContains(String text);
 
    @Query("SELECT * FROM article WHERE LENGTH(body) > :minLength")
    List<Article> findLong(int minLength);
}

Для поиска по строке ?q= в ArticleService появляется метод search(text), который вызывает findByTitleContains. В журнале видно, во что превратилось имя:

SELECT article_.`id`,article_.`title`,article_.`body` FROM `article` article_ WHERE (article_.`title` LIKE CONCAT('%',?,'%'))

Из чего складывается имя

ЧастьПримерSQL
findBy + полеfindByTitleWHERE title = ?
ContainsfindByTitleContainsLIKE '%…%'
GreaterThan, LessThanfindByIdGreaterThan>, <
And, OrfindByTitleAndBodyAND, OR
OrderBy + поле + Desc…OrderByIdDescORDER BY id DESC
countBy, existsBy, deleteBycountByTitleContainsCOUNT, проверка, DELETE

Если запрос не выразить именем, напишите SQL в @Query. Параметр :minLength связывается с аргументом метода по имени.

Постраничный вывод

PageableRepository добавляет findAll(Pageable). Контроллер принимает Pageable параметром — Micronaut соберёт его из page, size и sort в адресе:

// src/main/java/com/example/ArticleController.java
@Get("/page")
public Page<Article> page(Pageable pageable) {
    return articleService.findPage(pageable);
}

В сервисе findPage просто вызывает articleRepository.findAll(pageable). Запрос curl "http://localhost:8080/articles/page?page=0&size=2" при трёх статьях вернёт:

{"content":[{"id":1,"title":"Привет, Micronaut","body":"Первая статья"},{"id":2,"title":"Записи в Java","body":"Вторая статья"}],"pageable":{"size":2,"number":0,"sort":{},"mode":"OFFSET"},"totalSize":3}

Номер страницы начинается с нуля, totalSize — сколько записей всего. Сортировка задаётся так: ?page=1&size=2&sort=title.

Комментарии

Комментарий хранит номер своей статьи:

// src/main/java/com/example/Comment.java
@Serdeable
@MappedEntity
public record Comment(
        @Id @GeneratedValue @Nullable Long id,
        Long articleId,
        String author,
        String text) {
}
// src/main/java/com/example/CommentRepository.java
@JdbcRepository(dialect = Dialect.H2)
public interface CommentRepository extends CrudRepository<Comment, Long> {
 
    List<Comment> findByArticleId(Long articleId);
 
    long countByArticleId(Long articleId);
}

Поле articleId хранится в колонке article_id. CommentController с адресом /articles/{articleId}/comments отдаёт findByArticleId(articleId) на GET и сохраняет комментарий на POST. Проверка:

curl -X POST http://localhost:8080/articles/1/comments \
  -H "Content-Type: application/json" -d '{"author":"Oleg","text":"Отличная статья"}'
curl http://localhost:8080/articles/1/comments
[{"id":1,"articleId":1,"author":"Oleg","text":"Отличная статья"}]

Частая ошибка

Опечатка в имени поля ломает сборку, а не работу приложения. Метод findByHeadline в репозитории статей даёт при компиляции:

[ERROR] ArticleRepository.java:[19,19] Unable to implement Repository method: com.example.ArticleRepository.findByHeadline(String headline).
Cannot query entity [Article] on non-existent property: Headline [title, body]

В квадратных скобках Micronaut перечисляет поля, которые есть у сущности, — выберите нужное.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.