4

In my Oracle-database table mytable I have a column columnx with JSON-Arrays (VARCHAR2) and I would like to find all entries where the value valueX is inside that array.

In native Oracle-SQL the following query is working very well: SELECT * FROM mytable t WHERE JSON_EXISTS(columnx, '$?(@ == "valueX")');

In my Spring Boot Application I write queries in JPQL, so I have to convert it.

The following queries were unsuccessful:

  1. I found out that I have to use 'FUNCTION()' for specific SQL-Oracle-functions: @Query(value = "SELECT t FROM mytable t WHERE FUNCTION('JSON_EXISTS',t.columnx, '$?(@ == \"valueX\")')") That results in a JPQL-Parsing-Error: "QuerySyntaxException: unexpected AST node: function (JSON_EXISTS)"

  2. I found out that JPQL needs a real boolean-comparison, so I tried this: @Query(value = "SELECT t FROM mytable t WHERE FUNCTION('JSON_EXISTS',t.columnx, '$?(@ == \"valueX\")') = TRUE") Now the JPQL-Converter can parse it to native SQL successfully, but I got an Oracle-Error while executing the query: "ORA-00933: SQL command not properly ended." That's understandable since the parsed native ... WHERE JSON_EXISTS(columnx, '$?(@ == "valueX")') = 1 won't run either.

What is the right way to solve this problem? Do you have any idea?

EDIT: This is the field definition in JAVA:

@TypeDef(name = "json", typeClass = JsonType.class)
public class Mytable {
    ...
    @NotNull
    @Type(type = "json")
    @Column(columnDefinition = "VARCHAR2")
    private List<String> columnx;

2 Answers 2

1

you can try the below using native query.

@Query(value = "SELECT * FROM mytable t WHERE 
JSON_EXISTS(columnx, '$?(@ == \"valueX\")')", 
nativeQuery = true)

OR You can hide the JSON_EXISTS implementation inside a view in oracle and call the view in JPQL.

    create or replace view my_table_json_exists as SELECT * FROM 
    mytable t WHERE 
    JSON_EXISTS(t.columnx, '$?(@ == "valueX")');

   @Query(value ="select t from my_table_json_exists t");

If you are only looking for valueX inside a json key then you can explore JSON_VALUE.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your answer. Sure, the native query works fine, but I can't use it, because there is a complex filtering system in querydsl with a set of dynamic parameters, so that I need the JPQL form. Unfortunately the JPQL with your CASE-WHEN-THEN-ELSE cannot be parsed and I get this exception: Caused by: java.lang.NullPointerException: Cannot invoke "Object.getClass()" because the return value of "antlr.collections.AST.getNextSibling()" is null
Can you share one sample data with valueX from your JSON column
1
+50

In JPQL use MEMBER OF operator to check if a value is contained in a JSON array stored in a column. The JPQL query would look something like this:

@Query("SELECT t FROM mytable t WHERE :valueX MEMBER OF t.columnx")
List<Mytable> findByValueX(@Param("valueX") String valueX);

2 Comments

Thanks for your answer. That JPQL get parsed to ... WHERE 'valueX' in (SELECT ...) which returns in Oarcle-DB an empty list, because the column-type is VARCHAR2. Oracle doesn't look inside the Array.
What exactly you see inside that (SELECT ..)?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.