Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用JPA按JSON内容筛选行_Jpa_Spring Data Jpa_Jpql - Fatal编程技术网

使用JPA按JSON内容筛选行

使用JPA按JSON内容筛选行,jpa,spring-data-jpa,jpql,Jpa,Spring Data Jpa,Jpql,大约一周前,我发布了一篇文章,旨在解决如何基于多个列中的JSON值过滤行的问题。所提供的答案引起了以下疑问: select * from table_name where exists ( select 1 from jsonb_each_text(column1) as t(k,v) where v ilike '%string%') or exists ( select 1 from jsonb_

大约一周前,我发布了一篇文章,旨在解决如何基于多个列中的JSON值过滤行的问题。所提供的答案引起了以下疑问:

select *
from table_name
where
    exists (
        select 1
        from jsonb_each_text(column1) as t(k,v)
        where v ilike '%string%') or
    exists (
        select 1
        from jsonb_each_text(column2) as t(k,v)
        where v ilike '%string%');
该查询针对Postgres 9.6版本,并且缺少任何特定于Postgres的JSON运算符

我现在想将此查询转移到JPA存储库,但由于查询太大,需要使用
Pageable
进行排序和分页,如果可能,我想使用标准API。这些是我的实体

查询实体

@Data
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "change_log")
@EqualsAndHashCode
@TypeDefs({
        @TypeDef(name = "json", typeClass = JsonStringType.class),
        @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
public class ChangeEntity {

    @Id
    @Column(name = "id", nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long changeId;

    @ManyToOne(cascade = CascadeType.REFRESH, fetch = FetchType.LAZY)
    @JoinColumn(name = "entity_id", referencedColumnName = "id", nullable = false)
    @EqualsAndHashCode.Exclude
    private TrackedEntity entity; //not relevant

    @Type(type = "jsonb")
    @Column(name = "change", nullable = false,columnDefinition = "json")
    private String newValue;

    @Type(type = "jsonb")
    @Column(name = "previous",columnDefinition = "json")
    private String previousValue;

    @Column(name = "changed_at", nullable = false)
    private ZonedDateTime changedAt;

    @Type(type = "jsonb")
    @Column(name = "specific_changes",columnDefinition = "json")
    private String specificChanges;

    @ManyToMany(mappedBy = "entity")
    private Set<ChangeTagEntity> tags; //not relevant

}

我的问题是:


  • 如何编写表示
    存在(…)
    部分的谓词
  • 如果CriteriaAPI不能处理这个问题,那么查询的
    部分在JPQL中会是什么样子

  • 恐怕那是不可能的。您可以在JPQL中表示函数部分,但无论如何都无法将
    表示为t(k,v)
    public interface ChangeRepository extends JpaRepository<ChangeEntity, Long>, JpaSpecificationExecutor {
    
        @Query("select cte from ChangeEntity cte " +
                "where :tag member of cte.tags")
        Page<ChangeEntity> findAllChangesByTag(@Param("tag") ChangeTagEntity tag, Pageable pageable);
    
        @Query("select cte from ChangeEntity cte " +
                "where :tag member of cte.tags and cte.changedAt between :start and :end")
        Page<ChangeEntity> findAllChangesByTagAndRange(@Param("tag") ChangeTagEntity tag, @Param("start") ZonedDateTime start, @Param("end") ZonedDateTime end, Pageable pageable);
    
        Optional<ChangeEntity> findFirstByEntityOrderByChangedAtDesc(TrackedEntity trackedEntity);
    
    }
    
    public class NewValueSearchCriteria implements Specification {
        
        private String searchText;
        
        @Override
        public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder criteriaBuilder) {
            return criteriaBuilder
                    .exists(
                            query
                                 .select(
                                         criteriaBuilder
                                                        .function("jsonb_each_text", Object.class, root.get("newValue")).as() //to be continued
                                                         //how do i finish this ?
    
                                         ).where()
                    );
        }
    }