Как написать собственный @Query в Spring Data JDBC?

Как в примерах Spring Data JDBC написать простой запрос в аннотации @Query?

например В LegoSet Repository, как добавить простой findByName запрос?

Когда я попробовал

@Query("select * from lego_set where name = :name") List<LegoSet> findByName(@Param("name") String name); выдает следующую ошибку:

org.springframework.data.mapping.MappingException: Could not read property @org.springframework.data.annotation.Id() @org.springframework.data.relational.core.mapping.Column(value=handbuch_id, keyColumn=)private java.lang.Long example.springdata.jdbc.basics.aggregate.Manual.id from result set!
...

> Caused by: org.hsqldb.HsqlException: Column not found: manual_handbuch_idat org.hsqldb.error.Error.error(Unknown Source) at org.hsqldb.error.Error.error(Unknown Source) `

Кроме того, справочный документ, похоже, скопирован из некоторого общего документа данных Spring, поскольку в нем упоминается производный запрос, который еще не существует в данных spring jdbc.


person Kevin Z    schedule 24.10.2018    source источник
comment
Вероятно, вам нужно установить nativeQuery = true. Обратитесь к petrikainulainen.net/programming/spring-framework/   -  person user1211    schedule 25.10.2018
comment
@ user1211 нет атрибута nativeQuery в аннотации @Query Spring Data JDBC, поскольку все запросы должны предоставляться на собственном диалекте SQL используемой базы данных.   -  person Jens Schauder    schedule 25.10.2018


Ответы (3)


Так же, как завершение ответа @jens-schauder:

Запрос должен быть таким:

    @Query("SELECT ls.id, ls.name, ls.min_age, ls.max_age, " +
            "h.handbuch_id AS manual_handbuch_id, h.author AS manual_author, h.text AS manual_text " +
            "FROM lego_set ls JOIN handbuch h ON ls.id = h.handbuch_id " +
            "WHERE name = :name")
    List<LegoSet> findByName(@Param("name") String name);

Используя этот метод, проходят следующие тесты:

    @Test
    public void so_52978700() {
        // prepare
        LegoSet cars = createLegoSet("Small Car - 01", 5, 10);
        cars.setManual(new Manual("Just put all the pieces together in the right order", "Jens Schauder"));
        repository.save(cars);

        // execute
        List<LegoSet> actual = repository.findByName("Small Car - 01");

        // verify
        assertThat(actual).hasSize(1);
        assertThat(actual.get(0).getName()).isEqualTo("Small Car - 01");
        assertThat(actual.get(0).getManual().getText()).isEqualTo("Just put all the pieces together in the right order");
    }
person einsA    schedule 26.11.2019

Сущность LegoSet имеет отношение 1: 1 к Manual. Spring Data JDBC выбирает такую ​​конструкцию с помощью соединения и ожидает репрезентативные столбцы в ResultSet.

Обратите внимание, что он ожидает, что столбцы будут представлять саму сущность Manual плюс столбец, образующий обратную ссылку на LegoSet. Кроме того, все имена столбцов должны начинаться с имени свойства + _, то есть в данном случае manual_.

Сообщение об ошибке фактически сообщает вам об отсутствующем столбце (по модулю отсутствующего пробела): Column not found: manual_handbuch_id.

В качестве альтернативы вы также можете указать свои собственные _ 9_

По поводу документации:

Вы в чем-то правы. Документация (почти) всех модулей Spring Data включает общую часть, которая легко приводит к путанице. Существует билет для перехода к лучшему решению.

person Jens Schauder    schedule 25.10.2018
comment
Из журнала я вижу, что собственный запрос для findAll () по умолчанию аналогичен тому, что вы упомянули, и я заменил свой запрос тем предложением plus where, которое сработало. Но не был уверен в соглашении об именах, таком как manual_handbuch_id. Также замечено от 1 до многих, это делается в отдельном запросе. Надеялся, что он тоже работает 1 на 1. Для более сложных случаев, когда у дочернего класса 1 на 1 есть собственный дочерний класс 1 на 1 и т. Д., Тогда написание SQL будет нетривиальным и подверженным ошибкам. - person Kevin Z; 25.10.2018
comment
Я согласен. Если у вас есть идея, как сделать это менее болезненным, создайте заявку. А пока, полагаю, я ожидаю, что люди будут много использовать специальные RowMappers для нетривиальных вещей. - person Jens Schauder; 25.10.2018
comment
Насколько сложно во внутренней реализации относиться к 1 к 1 так же, как к 1 ко многим? Если это просто по соображениям производительности, по крайней мере, было бы неплохо предоставить это как вариант. Другой подход - предоставлять производные запросы как другие данные Spring, которые должны охватывать более 90% наших случаев. Я вспомнил, что вы упомянули, что он уже в пути на ваших семинарах? Надеюсь, скоро увидим. Спасибо. - person Kevin Z; 25.10.2018
comment
Присоединение к 1: произойдет много. То же самое для вывода запросов. Я думал об упрощении написания пользовательских запросов. - person Jens Schauder; 25.10.2018
comment
Думаю, я не совсем понимаю различия между Руководством и Моделью в этом примере. Они оба являются частью совокупности, почему в \ @Query я должен конкретно иметь дело с руководством, а не с моделью? В идеале мне не нужно беспокоиться о дочерних объектах в \ @Query. - person Kevin Z; 25.10.2018
comment
Техническая причина заключается в том, что к совокупному корню можно присоединить любое количество взаимно однозначных отношений. Но с «один ко многим» в настоящее время ни одна из них не присоединяется (ожидается), поскольку, когда у вас более одной такой связи, вам нужно выбрать одну, к которой вы хотите присоединиться. В противном случае вы получите кросс-продукт с огромной мощностью. - person Jens Schauder; 26.10.2018
comment
Поддерживает ли Spring data jdbc настраиваемые изменяемые запросы, например пользовательский запрос на вставку? Я получаю A result was returned when none was expected. - person Tobi Akinyemi; 16.10.2020
comment
@TobiAkinyemi Да, это так: github.com/spring-projects/spring-data-jdbc/blob/ - person Jens Schauder; 16.10.2020
comment
Я видел, как обновления работают нормально, но не вставки (возвращающие идентификатор). Это отлично работало с JPA - person Tobi Akinyemi; 16.10.2020
comment
Вероятно, проблема в возврате идентификатора @TobiAkinyemi. Хотите создать проблему? jira.spring.io/browse/DATAJDBC - person Jens Schauder; 16.10.2020
comment
@JensSchauder Просто чтобы уточнить, нельзя ли с помощью spring data jdbc выполнить эту вставку и получить идентификатор? - person Tobi Akinyemi; 16.10.2020
comment
@TobiAkinyemi в настоящее время не поддерживает аннотацию запроса. Стандартное сохранение делает это. Или вы можете написать для него собственный метод. - person Jens Schauder; 16.10.2020
comment
Давайте продолжим это обсуждение в чате. - person Jens Schauder; 16.10.2020

Я думаю, вы пытаетесь выполнить собственный запрос. Попробуйте, как показано ниже.

@Query(  value = "SELECT * FROM lego_set ls where ls.name = :name",
           nativeQuery = true)
  List<LegoSet> findByName(@Param("name") String name);

Это должно сработать.

person Abdullah Al Mamun    schedule 25.10.2018
comment
Это относится к Spring data jdbc, а не только к spring data jpa, поэтому nativeQuery не будет работать. - person Kevin Z; 25.10.2018