Spring Boot 使用Map的JPA查询元素集合进行选择[重复]

2guxujil  于 2022-11-23  发布在  Spring
关注(0)|答案(1)|浏览(124)

此问题在此处已有答案

JPA's Map<KEY, VALUE> query by JPQL failed(3个答案)
13个小时前关门了。
我遇到了一个问题,因为我们的设置假设属性在一个实体中。我想查询该属性,并检查是否存在具有特定值的属性键。如果是这样,我将返回该对象。下面是该解决方案的伪代码,其中包含我感兴趣的字段。

@Entity
@Table(name = "some")
class Some {

    @Id
    private Long id;

    @Convert(converter = ConverterToJson.class, attributeName = "value")
    @ElementCollection
    @CollectionTable(name = "some_properties", joinColumns = @JoinColumn(name = "object_id"))
    @MapKeyColumn(name = "property_key")
    @Column(length = 4000)
    private Map<String, Object> properties = new HashMap<>();
    
    
}

在该结构中,我想执行如下查询:

@Query(value = "SELECT so FROM Some so JOIN so.properties prop WHERE prop.key = 'searchedKey' AND prop.value = :searchedValue")
    Set<Some> findAllBySearchedKeyEqual(@Param("searchedKey") Long searchedValue);

我已经试过了,当然这不是有效的查询。有人知道如何正确地做这个查询吗?
编辑
经过更多的研究,我发现您应该使用VALUE()和KEY()方法,但现在的问题是有一个嵌套的select返回多个结果。

@Query(value = "SELECT DISTINCT so FROM Some so INNER JOIN so.properties prop " +
            "WHERE ((KEY(prop)) = 'searchedKey' AND (VALUE(prop)) = ':searchedValue')")
    Set<Some> findAllBySearchedKeyEqual(@Param("searchedKey") Long searchedValue);

我曾经用过一些这样的回答:Spring data JPA/hibernate query over java.util.Map keys?

2w2cym1i

2w2cym1i1#

您的问题更多的是设计问题不良实践,而不是程序错误。这就是为什么没有简单/适当的方法来获取您需要的数据。您几乎永远不希望实体中有散列表对象。更好的做法是创建另一个名为SomeProperties的实体,并将Some对象的所有属性与SomeProperties示例链接。

@Entity
@Table(name = "some")
class Some {

    @Id
    private Long some_id;

    @OneToMany(mappedBy="some")
    private Set<SomeProperties> properties = new ArrayList<>(); 
}

@Entity
@Table(name = "some_properties")
class SomeProperties {

    @Id
    private Long property_id;

    @ManyToOne
    @JoinColumn(name="some_id", nullable=false)
    private Some some;

    @Column(value = "key")
    private String key;

    @Column(value = "value")
    private Long value;
}

这样,您就可以更安全、更方便地管理Some及其属性。
另外,您的查询方法中也有错误。您只传递了一个参数,但您需要同时传递键和值才能匹配。您的查询将如下所示。
在您的Some存储库中:

@Query("select s from Some s inner join s.properties p where p.key = :key and p.value = :value")
Set<Some> findAllByKeyAndValueEqual(@Param("key") String key, @Param("value") Long value);

相关问题