Запрос загрузочного репозитория Spring с использованием Set - InvalidDataAccessApiUsageException - PullRequest
0 голосов
/ 30 апреля 2019

У меня есть API весенней загрузки, вызываемый из пользовательского интерфейса React, который извлекает некоторые данные с помощью запроса в хранилище весенней загрузки.Тем не менее, я получаю сообщение об ошибке, когда я ввожу использование Set <> в параметры запроса, и я не уверен, что делать дальше.

Ошибка выглядит следующим образом: org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [WaterHardness(id=4, hardness=hard)] did not match expected type [java.util.Set (n/a)]; nested exception is java.lang.IllegalArgumentException: Parameter value [WaterHardness(id=4, hardness=hard)] did not match expected type [java.util.Set (n/a)]

Из того, что я исследовал (я не нашел полных примеров, использующих ManyToMany Set<>), я подумал, что должен был бы использовать и IN в операторе запроса вместе с переданным в Set<> параметром.

У меня есть метод контроллера, который берет POST из приложения реагирования:

@PostMapping("/search")
@ResponseBody
public String searchFish(@RequestBody FishDto fishDto) {
    String fishJson = "";
    try {
        List<Fish> fish = fishService.findBySearch(fishDto);

        ObjectMapper mapper = new ObjectMapper();
        fishJson = mapper.writeValueAsString(fish);   
    } catch (Exception e) {
        //TODO Proper Handle of exceptions
        log.info("Something Went Wrong!!!");
    }
    return (fishJson);
}

Параметры вызова сопоставлены с FishDTO:

public class FishDto {

    private int tankVolume;
    private int tankLength;
    private int tankDepth;
    private int tankTemp;
    private Set<WaterHardness> waterHardness;

}

Выглядит так, как будтоDTO заполняется, как и ожидалось, при работе с отладчиком.

Контроллер вызывает метод в службе, который подготавливает параметры для хранилища:

public class FishService {
    ...
    public List<Fish> findBySearch(FishDto fishDto) {
        int tankVolume = fishDto.getTankVolume();
        int tankLength = fishDto.getTankLength();
        int tankDepth = fishDto.getTankDepth();
        int tankTemp = fishDto.getTankTemp();
        Set<WaterHardness> waterHardness = fishDto.getWaterHardness();

        return Lists.newArrayList(fishrepo.findBySearch(tankVolume, tankLength, tankDepth, tankTemp, waterHardness));
    }
...
}

Наконец, хранилище выполняет вызовиспользуя запрос:

public interface FishRepository extends JpaRepository<Fish, Long> {

    @Query("SELECT f FROM Fish f" 
        + " WHERE f.tankMinVolume <= :tankVolume"
        + " AND f.tankMinLength <= :tankLength"
        + " AND f.tankMinDepth <= :tankDepth"
        + " AND f.minWaterTemp <= :tankTemp"
        + " AND f.maxWaterTemp >= :tankTemp"
        + " AND f.waterHardness IN :waterHardness")
    List<Fish> findBySearch(@Param("tankVolume") int tankVolume,
        @Param("tankLength") int tankLength,
        @Param("tankDepth") int tankDepth,
        @Param("tankTemp") int tankTemp,
        @Param("waterHardness") Set<WaterHardness> waterHardness);
}

О, и вот модель сущностей, которая возвращается:

@Entity
@Table(name = "fish")
public class Fish {

    @Id
    @GeneratedValue
    private Long id;

    @NonNull //Check up on this!
    private String commonName;
    private String latinName;
    private int fullGrownSize;
    private int tankMinVolume;
    private int tankMinLength;
    private int tankMinDepth;
    private int minWaterTemp;
    private int maxWaterTemp;
    private int minShoalSize;

    @ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL)
    private Set<TankPlacement> tankPlacement;

    @ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL)
    private Set<TankFlow> tankFlow;

    @ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.ALL)
    private Set<WaterHardness> waterHardness;

    @ManyToOne(cascade=CascadeType.PERSIST)
    private Origin origin;

}

Есть ли удобный способ заставить это работать, помимо получения спискаid / строковое значение длям WaterHardness в службе и передачи их в качестве параметра, а затем с помощью объединений в запросе?Например:

@Query("SELECT f FROM Fish f" 
        + " JOIN f.waterHardness wh"
        + " WHERE f.tankMinVolume <= :tankVolume"
        + " AND f.tankMinLength <= :tankLength"
        + " AND f.tankMinDepth <= :tankDepth"
        + " AND f.minWaterTemp <= :tankTemp"
        + " AND f.maxWaterTemp >= :tankTemp"
        + " AND wh.id IN :waterHardnessIds")
    List<Fish> findBySearch(@Param("tankVolume") int tankVolume,
        @Param("tankLength") int tankLength,
        @Param("tankDepth") int tankDepth,
        @Param("tankTemp") int tankTemp,
        @Param("waterHardnessIds") List<Long> waterHardnessIds);

, который работает, но чувствует себя ненужным.

1 Ответ

0 голосов
/ 30 апреля 2019

Проблема Set<WaterHardness>.

Ошибка говорит,

Значение параметра [WaterHardness (id = 4, hardness = hard)] не соответствует ожидаемому типу [java.util.Set (n / a)]

Вам необходимо проверить оператор IN следующим образом:

открытый интерфейс FishRepository расширяет JpaRepository {

@Query("SELECT f FROM Fish f" 
    + " WHERE f.tankMinVolume <= :tankVolume"
    + " AND f.tankMinLength <= :tankLength"
    + " AND f.tankMinDepth <= :tankDepth"
    + " AND f.minWaterTemp <= :tankTemp"
    + " AND f.maxWaterTemp >= :tankTemp"
    + " AND f.waterHardness.id IN :waterHardness")
List<Fish> findBySearch(@Param("tankVolume") int tankVolume,
    @Param("tankLength") int tankLength,
    @Param("tankDepth") int tankDepth,
    @Param("tankTemp") int tankTemp,
    @Param("waterHardness") Set<Long> waterHardness);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...