Postgres JSONB Check if JSON contains string using JPA - postgresql

I have a jsonb column in my posgtgres table the json is of structure : {'alias':["name1","name2","name"....]}
I have written the Postgres query to check if the array in the JSON object contains the name.
select * from public.table t where json_col->'alias' ? 'name'
this works on pgAdmin
But same doesn't work in JPA
My code
#Query(value = "select * from public.table t where json_col->'alias' ? :name" ,nativeQuery = true)
Table findUsingName(#Param("name") String name);
This throws an error : 'Mixing of ? parameters and other forms like ?1 is not supported!'
I understand this error is due to the fact ? is also used by JPA is different sense...
Can anyone help me in the JPA Query

I don't know what the ? operator does, but you should use the named variant of the operator as a ? in JDBC is used to define a parameter.

Found the postgres function for '?' i.e. jsonb_exists_any(company_alias->'alias',ARRAY[:name])

Related

Why does Spring JPA #Query return an error when I omit the table alias?

I'm querying a PostgreSQL table with a very simple query using Spring Data JPA:
#Query(value = "SELECT id FROM location l", nativeQuery = true)
This works fine. However, if I omit the table alias and use:
#Query(value = "SELECT id FROM location", nativeQuery = true)
I get an error saying No Dialect mapping for JDBC type: 1111. ID is a UUID in both PostgreSQL and the DTO.
Why does this happen? As far as I can tell, that's a perfectly valid query, and I'm not even using the table alias in the working version. Adding #Type and #TypeMappings made no difference. I checked the data I'm querying, and all the IDs are valid.
I'm happy to use an alias now that I've figured this out, but I'm curious about what's happening behind the scenes that causes this to fail.
Spring Data JPA tries to parse your query in order to derive a count query or add/modify and ORDER BY clause.
This to some extend relies on having an alias for the main table/entity of the query.
It should give you a proper error that it can't find an alias instead of the weird error you are seeing.

Casting Integer to String in JPQL

I want to have a JPQL query that may look like:
entityManager.createQuery("Select a.* from A a WHERE CAST(a.num AS TEXT) LIKE '%345%' ", A.class);
where a.num is an integer. I want to cast this to String to use the LIKE criteria.
However above casting doesnt work in JPQL. Any idea about how can I implement this?
Could you be more specific, what your problem is? Do you have some kind of error or it the result of the query is just wrong?
Because this code works fine for me:
session.createQuery("from MyObject where CAST(id as text) like :id").setParameter("id", "%1").getResultList();
I am using Hibernate 5.2 and Postgresql 9.5.
Also, if you are having trouble understanding what goes wrong, you could try editing hibernate.cfg.xml or whatever configuration file you are using to make Hibernate show queries it sends, by doing something like this:
<property name="hibernate.show_sql">true</property>
I also have the same need. This should work with JPA 2.0 and Hibernate 5.0.2:
entityManager.createQuery(
"Select a.* from A a WHERE CONCAT(a.num, '') LIKE '%345%' ", A.class);
From hibernate document, "cast(... as ...)", where the second argument is the name of a Hibernate type. According list of Hibernate Types it should be string (case sensitive!).
So request should be:
entityManager.createQuery("select a.* from A a WHERE CAST(a.num AS string) LIKE '%345%' ", A.class);
Was taken and checked from Caused by: org.hibernate.QueryException: Could not resolve requested type for CAST : INT answer.
You can simply use CAST(num as string). It worked for me
Well you can use to_char() function in the select clause but, you will need to select all the a.num field separately and not with *.
And in postgresql you will need to specify a mask for to_char()function, so it would be to_char(field, mask), for example we can supply 'FM999999999999999999' as a mask to accept the maximum possible digits.
Your query would be something like this:
Select *, to_char(a.num, 'FM999999999999999999') as num from A a WHERE num LIKE '%345%'
You can take a look at Postgresql Data Type Formatting Functions for further details.
To write the query in your code with EntityManager you can create a native query using .createNativeQuery() method, this is how should be your code:
em.createNativeQuery("Select *, to_char(a.num, 'FM999999999999999999') as num from A a WHERE num LIKE '%345%'");
The correct query is :
entityManager.createQuery("Select a.* from A a WHERE CAST(a.num AS String) LIKE '%345%' ", A.class);

OpenJpa how to find length of string in JPQL

I am using
length(ze.string)>2 in openJpa query. but i am getting
SQLCODE=-440, SQLSTATE=42884, SQLERRMC=CHAR_LENGTH;FUNCTION, DRIVER=3.53.95 {prepstmnt 1776269692 SELECT t0.f1, t0.f2, t0.f3, t0.f4, t0.f5, t0.f6, t0.f7, t0.f8, t0.f9, t0.f10, t0.f11, t0.f12, t0.f13, t0.f14, t0.f15, t0.f16, t0.f17 FROM table t0 WHERE (t0.f1 = ? AND CHAR_LENGTH(?) > ? AND .....
In plain query when i do length operation i am getting record but using jpa its not working. I looked Here used size it doesn't work. and the field is varchar and db2. trying from past 1 hour.
DB2 requires use of the SQL function LENGTH, yet OpenJPA seems to be incorrectly converting your JPQL to use SQL function CHAR_LENGTH (hence the error message - not that DB2 gives out clear messages saying what is wrong, who knows what SQLCODE=-440 is without having to search!!).
Raise a bug on your JPA provider.
See https://www.ibm.com/support/knowledgecenter/SSEPGG_9.7.0/com.ibm.db2.luw.sql.ref.doc/doc/r0000818.html
You would need to give more details about your entity, persistence.xml, and query to get to the bottom or this. However, I do not see how OpenJPA would use CHAR_LENGTH instead of LENGTH for DB2. Let me explain. If you look at DBDictionary here:
https://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?view=markup
You can see it defines something called "stringLengthFunction" as follows:
public String stringLengthFunction = "CHAR_LENGTH({0})";
This is the string length function which should be used for each individual dictionary (i.e. Database config). However, for DB2, the AbstractDB2Dictionary, see here:
https://svn.apache.org/viewvc/openjpa/branches/2.2.x/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java?view=markup
overrides this as follows:
stringLengthFunction = "LENGTH({0})";
Given this, for DB2, LENGTH should be used. I took the following simple query:
"select me.id from MyEntity me where length(me.name)>2"
And executed it on OpenJPA using DB2, and I got this:
SELECT t0.ID FROM MYENTITY t0 WHERE (CAST(LENGTH(t0.ID) AS BIGINT) > CAST(? AS BIGINT)) [params=(long) 2]
Thanks,
Heath Thomann

PostgreSQL function round and JPA/Hibernate

I have a query which is executed from java application like this:
Query query = getEntityManager().createQuery(hql);
The query looks like this:
String hql = "select * from table a where round(column1, 3) = round(parameter, 3)";
Here column1 is of type Double. The value it holds is like 143.02856666. I need to retain the value as it is, but for some business logic just need to round and compare.
The initial database configured was H2 and this worked fine. Now the database has been changed to Postgres and this query now errors out.
ERROR: function round(double precision, integer) does not exist Hint: No function matches the given name and argument types. You might
need to add explicit type casts.
The round() function in Postgres takes a numeric datatype and needs a cast.
The below query works fine if executed directly in Postgres console.
select * from table a where round(cast(column1 as numeric), 3) = round(cast(parameter as numeric), 3);
The same from java application errors out.
java.lang.IllegalArgumentException: org.hibernate.QueryException: Could not resolve requested type for CAST : numeric
Also tried Query query = getEntityManager().createNativeQuery(hql);
This results in a new error.
org.hibernate.engine.jdbc.spi.SqlExceptionHelper - ERROR: syntax error at or near "where"
If I debug, this errors out when the below line is executed.
List resultList = query.getResultList();
How do I rewrite the query so that it works against Postgres ?
What you are doing with Query query = getEntityManager().createQuery(hql); is calling a jpql-query, which does not support all db-functions like round(v numeric, s integer).
Two Suggestions:
Use BETWEEN and maintain jpql-mapping
Write a NativeQuery -> Query query = em.createNativeQuery(queryString);
Your queryString just has to be altered by your parameters.

casting boolean type with doctrine 2 DQL

I have a doctrine entity A which has a field 'attendance' of type boolean. The values for this field are stored as t and f in postgres. I want to write a DQL which will give me the field value as 1 or 0. I can do the same in SQL with postgressql cast statement like below :
"select attendance::int from class where student = 1"
Doctrine extensions provides CAST function. Another option is NativeQuery or pure SQL query (if you don't need mapping).