I'm trying to crete Criteria API query with JSON_VALUE function() is Oracle12c:
select * from orderswhere (JSON_VALUE(duty, '$.department') in ( ? , ? , ? ,? , ? , ? , ?));
MODEL:
@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();
 };
 }
But getting exception: o.h.engine.jdbc.spi.SqlExceptionHelper: ORA-40454:path expression not a literal
I am searching for a long time on net. But no use. Please help or try to give some ideas how to achieve this.
ERROC CODE:
 2017年11月23日 12:26:55.271 WARN 11972 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 40454, SQLState: 99999
 2017年11月23日 12:26:55.271 ERROR 11972 --- [nio-8080-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : ORA-40454: path expression not a literal
- 
 error message:2017年02月15日 14:22:13.210 WARN 23176 --- [nio-8080-exec-7] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 40454, SQLState: 99999 2017年02月15日 14:22:13.210 ERROR 23176 --- [nio-8080-exec-7] o.h.engine.jdbc.spi.SqlExceptionHelper : ORA-40454: path expression not a literalAlex.Bob– Alex.Bob2017年02月15日 06:25:06 +00:00Commented Feb 15, 2017 at 6:25
1 Answer 1
The reason this is not working, is that in the background, Hibernate will generate such an SQL:
SELECT * FROM T WHERE JSON_VALUE(?, ?)=?
.. and this does not work with Oracle.
The solution is, to inline these values. First a small helper class:
public class HibernateInlineExpression extends LiteralExpression<String> {
 public HibernateInlineExpression(CriteriaBuilder criteriaBuilder, String literal) {
 super((CriteriaBuilderImpl) criteriaBuilder, literal);
 }
 @Override
 public String render(RenderingContext renderingContext) {
 return getLiteral();
 }
}
Using the above, you can now do JSON expressions in predicates:
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"));
Of course the above is a Hibernate-specific implementation, users of EclipseLink, etc. have to come up with something similar. See my blog post about using JSON functions of Oracle from JPA/Hibernate for some other tricks.
1 Comment
Explore related questions
See similar questions with these tags.