Spring 带有oracle12c JSON_值函数的JPA标准api

Spring 带有oracle12c JSON_值函数的JPA标准api,spring,hibernate,jpa,spring-boot,spring-data-jpa,Spring,Hibernate,Jpa,Spring Boot,Spring Data Jpa,我正在尝试将带有JSON_VALUE函数()的API查询定义为Oracle12c: select * from orderswhere (JSON_VALUE(duty, '$.department') in ( ? , ? , ? ,? , ? , ? , ?)); 型号: @Entity @Table(name = "orders") @EntityListeners(AuditingEntityListener.class) public class Trade implements S

我正在尝试将带有JSON_VALUE函数()的API查询定义为Oracle12c:

select * from orderswhere (JSON_VALUE(duty, '$.department') in ( ? , ? , ? ,? , ? , ? , ?));
型号:

@Entity
@Table(name = "orders")
@EntityListeners(AuditingEntityListener.class)
public class Trade implements Serializable {
     @Convert(converter = JpaConverterJson.class)
     private Map<String, Object> duty;
     .....
}

private Specification<InvoicePurchase> reportFormToSpec(Map<String, Object> 
    params) {
        return (root, query, cb) -> {
             List<Predicate> predicates = new ArrayList<>();
       if (!StringUtils.isEmpty(params.get("department"))) {
            Predicate predicate = cb.like(cb.function("json_value", String.class,
                    root.get("duty"),
                    cb.literal("$.department"))
                    , params.get("department"));
            predicates.add(predicate);
        }
            return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
        };

    }

这不起作用的原因是,在后台,Hibernate将生成这样一个SQL:

SELECT * FROM T WHERE JSON_VALUE(?, ?)=?
。。这对Oracle不起作用

解决方案是,内联这些值。首先是一个小助手类:

public class HibernateInlineExpression extends LiteralExpression<String> {

  public HibernateInlineExpression(CriteriaBuilder criteriaBuilder, String literal) {
      super((CriteriaBuilderImpl) criteriaBuilder, literal);
  }

  @Override
  public String render(RenderingContext renderingContext) {
      return getLiteral();
  }
}
公共类HibernateInlineExpression扩展了LiteralExpression{
公共HibernateInlineExpression(CriteriaBuilder CriteriaBuilder,字符串文字){
超级((CriteriaBuilderImpl)criteriaBuilder,文字);
}
@凌驾
公共字符串渲染(RenderingContext RenderingContext){
返回getLiteral();
}
}
使用上述方法,您现在可以在谓词中执行JSON表达式:

cb.equal(cb.function("JSON_VALUE", String.class,
                new HibernateInlineExpression(cb, "JSON_COLUMN"),
                new HibernateInlineExpression(cb, "'$.my.json.property'")),
  new LiteralExpression<>((CriteriaBuilderImpl) cb, String.class, "somevalue"));
cb.equal(cb.function(“JSON_值”),String.class,
新的HibernateInlineExpression(cb,“JSON_列”),
新的HibernateInlineExpression(cb,“$.my.json.property”),
新的文字表达式((CriteriaBuilderImpl)cb,String.class,“somevalue”);

当然,上面是一个特定于Hibernate的实现,EclipseLink等的用户必须想出类似的方法。查看my了解其他一些技巧。

错误消息:2017-02-15 14:22:13.210警告23176---[nio-8080-exec-7]o.h.engine.jdbc.spi.SqlExceptionHelper:SQL错误:40454,SQLState:9992017-02-15 14:22:13.210错误23176---[nio-8080-exec-7]o.h.engine.jdbc.spi.SqlExceptionHelper:ORA-40454:路径表达式不是文字
cb.equal(cb.function("JSON_VALUE", String.class,
                new HibernateInlineExpression(cb, "JSON_COLUMN"),
                new HibernateInlineExpression(cb, "'$.my.json.property'")),
  new LiteralExpression<>((CriteriaBuilderImpl) cb, String.class, "somevalue"));