微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用spring数据jpa查询jsonb列?

我在使用postgres 9.4实例获取此本机查询时遇到问题.

我的存储库有一个方法

 @Query(value = "SELECT t.* " +
            "FROM my_table t " +
            "WHERE t.field_1 = ?1 " +
            "AND t.field_2 = 1 " +
            "AND t.field_3 IN ?2 " +
            "AND t.jsonb_field #>> '{key,subkey}' = ?3",
            nativeQuery = true)
    List<Entity> getEntities(String field1Value,
                                   Collection<Integer> field3Values,
                                   String jsonbFieldValue);

但是日志显示了这个:

SELECT t.* FROM my_table t 
WHERE t.field_1 = ?1 
  AND t.field_2 = 1 
  AND t.field_3 IN ?2 
  AND t.jsonb_field ? '{key,subkey}' = ?3

我得到这个例外:

Internal Exception: org.postgresql.util.PsqlException: No value
specified for parameter 2.

我在方法调用之前直接记录了参数,并且它们都是提供的.

我不确定为什么#>>显示?在日志中.我是否需要逃避#>>?我需要格式化IN的集合吗?我需要逃离json路径吗?

当我直接对db执行查询时,它可以工作.例:

SELECT *
FROM my_table t
WHERE t.field_1 = 'xxxx'
  AND t.field_2 = 1
  AND t.field_3 IN (13)
  AND t.jsonb_field #>> '{key,subkey}' = 'value'

解决方法:

我发现Spring数据中的Specification api非常有用.
假设我们有一个名为Product的实体和一个名称类型为JSON(B)的属性.
我假设此属性包含不同语言的产品标题.一个例子可以是:{“EN”:“多色LED灯”,“GR”:“ΠολύχρωμοLEDφώς”}.
下面的源代码通过标题和作为参数传递的语言环境找到(或者更多,如果它不是唯一字段)产品.

@Repository
public interface ProductRepository extends JpaRepository<Product, Integer>, JpaSpecificationExecutor<Product> {
}


public class ProductSpecification implements Specification<Product> {

    private String locale;
    private String titletoSearch;

    public ProductSpecification(String locale, String titletoSearch) {
        this.locale = locale;
        this.titletoSearch = titletoSearch;
    }

    @Override
    public Predicate toPredicate(Root<Product> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
        return builder.equal(builder.function("jsonb_extract_path_text", String.class, root.<String>get("title"), builder.literal(this.locale)), this.titletoSearch);
    }
}


@Service
public class ProductService {

    @Autowired
    private ProductRepository productRepository;

    public List<Product> findByTitle(String locale, String titletoSearch) {
        ProductSpecification cs = new ProductSpecification(locale, titletoSearch);
        return productRepository.find(cs);
        // Or using lambda expression - without the need of ProductSpecification class.
//      return productRepository.find((Root<ProductCategory> root, CriteriaQuery<?> query, CriteriaBuilder builder) -> {
//          return builder.equal(builder.function("jsonb_extract_path_text", String.class, root.<String>get("title"), builder.literal(locale)), titletoSearch);
//      });
    }
}

您可以找到有关使用Spring Data here方法的另一个答案.
希望有所帮助.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐