Использование SQL-IN-предложения в пользовательском @Query в JPA- / CrudRepository со списком или в качестве переданного параметра? - PullRequest
0 голосов
/ 30 октября 2018

Привет, эксперты по Spring и Hibernate!

Может ли кто-нибудь сказать, можно ли использовать SQL IN-предложение в пользовательском @Query в CrudRepository, в то время как Arraylist или набор строк передаются в качестве параметра?

Я относительно новичок в Spring и не совсем понимаю, почему я получаю следующую ошибку Spring:

"java.lang.IllegalArgumentException: значение параметра [d9a873ed-3f15-4af5-ab1b-9486017e5611] не соответствует ожидаемому типу [IoTlite.model.Device (n / a)]"

В этом посте ( JPQL IN: Java-массивы (или списки, наборы ...)? ) тема обсуждается довольно близко, но я не могу заставить предлагаемое решение работать в моем случае с custom @ Query.

Мой демонстрационный репозиторий как часть приложения restful для весенней загрузки выглядит следующим образом:

@Repository
public interface DeviceRepository extends JpaRepository<Device, Long> {        
    @Query("SELECT d FROM Device d WHERE d IN (:uuid)")
    List<Device> fetchUuids(@Param("uuid") Set<String> uuid);
}

А модель-класс выглядит следующим образом:

@Entity
@SequenceGenerator(sequenceName = "device_seq", name = "device_seq_gen", allocationSize = 1)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Device implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "device_seq_gen")
    @JsonIgnore
    private Integer id;

    @Column(unique=true, length=36)
    @NotNull
    private String uuid = UUID.randomUUID().toString();

    @Column(name="name")
    private String name;

    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String description;

    @OneToMany(
            mappedBy="device",
            cascade = CascadeType.ALL,
            orphanRemoval = true
    )
    private List<Sensor> sensors = new ArrayList<>();


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @JsonIgnore
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getDeviceUuid() {
        return uuid;
    }

    public void setDeviceUuid(String deviceUuid) {
        this.uuid = deviceUuid;
    }

    public List<Sensor> getSensors() {
        return sensors;
    }

    public void addSensor(Sensor sensor){
        sensor.setDevice(this);
        sensors.add(sensor);
    }

}

Вот соответствующая часть службы, вызывающая метод fetchUuids-custom-с параметром set-list строк (служба, естественно, вызывается соответствующим restcontroller):

@Service
public class DeviceService implements IDeviceService {

    @Autowired 
    private DeviceRepository deviceRepository;

...

    @Override
    public List<Device> listDevices(Set<String> clientIds) {
        return deviceRepository.fetchUuids(clientIds);
    }
...
}

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

Быстрое исправление

У вас есть WHERE d IN (:uuid) в пользовательском запросе. Вы не можете сопоставить d, который является псевдонимом для Device сущности с параметром :uuid, который является коллекцией строк.

WHERE d.uuid IN (:uuid) исправит запрос - он соответствует строке со строками.

Что вы должны сделать вместо этого

Довольно неправильно вводить имя метода fetchUuids и возвращать список Device экземпляров. Для этого также нет необходимости писать собственный запрос. Вы можете воспользоваться соглашениями об именах методов репозитория и позволить среде Spring Data Jpa сгенерировать запрос для вас:

List<Device> findByUuidIn(Set<String> uuids);
0 голосов
/ 30 октября 2018

Да возможно использование коллекции в параметрах запроса JPA. Ваш запрос неверен, он должен выглядеть следующим образом:

@Query("SELECT d FROM Device d WHERE d.uuid IN :uuid")
...