java - 在 JPA-/CrudRepository 中的自定义 @Query 中使用 SQL-IN 子句并将列表或设置为传递参数?

标签 java spring hibernate spring-data-jpa jpa-2.0

Spring 和 Hibernate 专家您好!

有人能说一下,当 Arraylist 或一组字符串作为参数传递时,是否可以在 CrudRepository 的自定义 @Query 中使用 SQL IN 子句吗?

我对 Spring 比较陌生,不太明白为什么会出现以下 Spring 错误:

“java.lang.IllegalArgumentException:参数值 [d9a873ed-3f15-4af5-ab1b-9486017e5611] 与预期类型 [IoTlite.model.Device (n/a)] 不匹配”

在这篇文章 ( JPQL IN clause: Java-Arrays (or Lists, Sets...)? ) 中,该主题进行了非常仔细的讨论,但我无法使用自定义 @Query 使建议的解决方案适用于我的情况。

作为 Spring Boot 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-method 的服务的相关部分,以字符串设置列表作为参数(服务自然由相关的 Restcontroller 调用):

@Service
public class DeviceService implements IDeviceService {

    @Autowired 
    private DeviceRepository deviceRepository;

...

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

最佳答案

快速修复

自定义查询中有 WHERE d IN (:uuid)。您无法将 d(它是 Device 实体的别名)与 :uuid 参数(字符串集合)相匹配。

WHERE d.uuid IN (:uuid) 将修复查询 - 它将字符串与字符串进行匹配。

你应该做什么

将方法命名为 fetchUuids 并返回 Device 实例列表是相当具有误导性的。也无需编写自定义查询来执行此操作。您可以受益于存储库方法名称约定,让 Spring Data Jpa 框架为您生成查询:

List<Device> findByUuidIn(Set<String> uuids);

关于java - 在 JPA-/CrudRepository 中的自定义 @Query 中使用 SQL-IN 子句并将列表或设置为传递参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53060893/

相关文章:

mysql - Hibernate findById 没有找到它以前找到的记录

java - 在调用 save() hibernate 4.3 之前必须手动分配此类的 ids

java - 将字节转换为 GB 是否正确?

java - jsp 中的警告 : The tag handler class for "s:form" (org. apache.struts2.views.jsp.ui.FormTag) 在 Java 构建路径上找不到

Spring jsp 形式的 Eclipse 警告 “List is a raw type”

mysql - Elastic Beanstalk hibernate MySQL

java - 未找到 JSF actionListener 方法

java - Java 中的 transient

java - 当我尝试从 sessionFactory 打开 hibernate 获取 session 时,出现 org.apache.wicket.WicketRuntimeException

java - 如何使用 Spring 异常处理 POST REST 正确的错误状态代码