使用JPA按JSON内容筛选行
大约一周前,我发布了一篇文章,旨在解决如何基于多个列中的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_
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
}
我的问题是:
存在(…)
部分的谓词部分在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()
);
}
}