casting boolean type with doctrine 2 DQL - postgresql

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).

Related

Postgres JSONB Check if JSON contains string using JPA

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])

Custom column extension for slick

SQL expression generated by table.filter(_.id.inSetBind(someSet)) has restrictions for Oracle DB:
someSet must contains no more than 1000 elements (ORA-01795)
Oracle builds different excecution plans for queries with different size of someSet.
I want to create column extension, inArrayBind[T](s: Traversable[T]), that instead of creating query select ... where x IN (...), first creates Oracle type create or replace type MY_ARRAY IS varray(sizeOfSet) of type T and then perfrorms select ... where x in MY_ARRAY
Is there way to achieved this with slick?

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.

JPQL / JPA query to order entities based on the greatest/maximum of two columns?

I need something similar to this SQL query:
SELECT * FROM foo f ORDER BY GREATEST(f.bar_date, f.baz_date)
As not all RDBMS systems support the GREATEST function, ideally I would like the JPA implementation to generate the correct SQL query for the underlying database. The databases that I am targetting are Oracle, SQL Server, and PostgreSQL.
JPQL allows the FUNCTION operator to call a database function.
Oracle and Postgres support GREATEST, I don't think SQL Server does, so for it you may be able to write your own function.
You could also use a CASE function with >.
To put this a little more concrete - you could do this in JPQL with the CASE statement, which is supported since JPA 2.0. I've omitted the _date suffixes for brevity.
SELECT * FROM foo f ORDER BY CASE WHEN f.bar > f.baz THEN f.bar ELSE f.baz END
I've used CASE function.
Via criteria builder it looks like:
CriteriaQuery<?> query = ...
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
query.orderBy(builder.selectCase().when(builder.greaterThan(pathToBarDate, pathToBazDate),pathToBarDate).otherwise(pathToBazDate));
In JPQL it should look like
ORDER BY
CASE WHEN (f.bar_date>f.baz_date) THEN f.bar_date
ELSE f.baz_date