使用Set的Spring Boot Repository查询-InvalidDataAccessApiUsageException

时间:2019-04-30 14:09:50

标签: java spring-boot spring-data-jpa

我有一个从React UI调用的spring boot API,它使用spring boot存储库中的查询来获取一些数据。但是,当我在查询参数中引入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以及传入的{{ 1}}参数。

我有一个控制器方法,该方法从react应用程序中获取POST:

Set<>

调用中的参数被映射到FishDTO:

@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);
}

使用调试器运行时,似乎DTO已按预期填充。

控制器调用服务中的方法,该方法为存储库准备参数:

public class FishDto {

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

}

最后,存储库使用查询进行呼叫:

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);
}

除了从服务中的waterHardness获取id / string值列表并将它们作为参数传递然后在查询中使用联接之外,是否有一种巧妙的方法使它起作用?例如:

@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;

}

确实可以,但是感觉没有必要。

1 个答案:

答案 0 :(得分:0)

问题是Set<WaterHardness>

错误说

  

参数值[水硬度(id = 4,硬度=硬)]不匹配   预期的类型[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);
}