Add sql translate to a criteriaBuilder JPQL - java

I have a need to incorporate a plsql TRANSLATE(string1, string_to_replace, replacement_string) function to my query.
I am using javax.persistence.criteria.CriteriaBuilder to build my query in my java.
What I want to do is to do a simmilar query than this in java with a criteriaBuilder:
select * from person t where UPPER(TRANSLATE(t.name,'áàâäÁÀÂÄéèêëÉÈÊËíìïîÍÌÏÎóòöőôÓÒÖŐÔúùûüűÚÙÛÜŰ','aaaaAAAAeeeeEEEEiiiiIIIIoooooOOOOOuuuuuUUUUU')) LIKE UPPER('%variable%')
The ('%variable%') is my variable in java.
My problem is how do I build a similar query in jpql?
Right now I have :
Predicate pName = criteriaBuilder.like(criteriaBuilder.upper(root.<String> get("name")), "%" + dtp.getName().trim().toUpperCase() + "%");
wich is the equivalent of :
select * from person t where upper(t.name) like upper('%variable%')
Is translate function supported in JPQL?
Is it doable?
Do I need a Gandalf like Wizard?

You can use the method "function":
Expression<String> func = criteriaBuilder.function("translate", String.class, criteriaBuilder.upper(root.<String> get("name")),
criteriaBuilder.literal("áàâäÁÀÂÄéèêëÉÈÊËíìïîÍÌÏÎóòöőôÓÒÖŐÔúùûüűÚÙÛÜŰ"), criteriaBuilder.literal("aaaaAAAAeeeeEEEEiiiiIIIIoooooOOOOOuuuuuUUUUU"));
Predicate pName = criteriaBuilder.like(func, "%" + dtp.getName().trim().toUpperCase() + "%");

Related

JPA Query incorrectly uses parenthesis which results in a different query

I need to retrieve all the T1 objects from a table based on a condition where the expire date is null and the query should retrieve only T16_ID of three types which are A, B and C. I have the below simple SQL query for this which returns the correct result.
SELECT * FROM T1 d
WHERE d.T1_T2_ID_FK = '123'
AND d.T1_DATE_EXPIRED IS NULL
AND (d.T16_ID LIKE 'A' OR
d.T16_ID LIKE 'B'
OR d.T16_ID LIKE 'C');
I use JPA for object relational mapping in my application and below is my respective JPA query
TypedQuery<T1Docs> query = em.createQuery(
"**SELECT t FROM T1Docs t WHERE t.t1ID.t2Id = :idNum
AND t.t1DateExpired IS NULL
AND (t.t16DocType.t16Id LIKE :docType1 OR t.t16DocType.t16Id LIKE :docType2 OR t.t16DocType.t16Id LIKE :docType3**)",T1Docs.class);
query.setParameter("idNum", idNumber);
query.setParameter("docType1", "%" + "A" + "%");
query.setParameter("docType2", "%" + "B" + "%");
query.setParameter("docType3", "%" + "C" + "%");
above query doesnt return any result and when I debug the plogram I found that the query is generated as below.
SELECT t0.T1_ID, t0.T1_DATE_CAPTURED, t0.T1_DATE_EXPIRED, t0.T1_T16_ID_FK
FROM T1_OWNER_DOCUMENT t0, T16_DOC_TYPE t1 WHERE ((((t0.T1_T2_ID_FK = ?)
AND (t0.T1_DATE_EXPIRED IS NULL))
AND ((t1.T16_ID LIKE ? OR t1.T16_ID LIKE ?)
OR t1.T16_ID LIKE ?)) AND (t1.T16_ID = t0.T1_T16_ID_FK))
because of the incorrect usage of parenthesis, the generated query becomes incorrect and It doesn't return any result.
If anyone knows how to fix this issue in the JPA query because I am new to JPA and having trouble in understanding how to use OR with multiple checks along with AND and parenthesis.

JAVA EclipseLink optional query parameters

I have query which filters items by certain conditions:
#NamedQueries({
#NamedQuery(
name = ITEM.FIND_ALL_PARAMS_BY_COMPANY_COUNTRY_GROUP,
query = "SELECT i FROM Item i where "
+ "((i.idCompany=:companyId AND i.idEMGroup=:groupId) "
+ "OR (i.idCompany=:companyId AND i.idEMCountry =:countryId AND i.idEMGroup is null) "
+ "OR (i.idCompany is null AND i.idEMCountry = :countryId AND i.idEMGroup is null)) "
+ "order by i.idEMCountry desc, i.idCompany desc, i.idEMGroup desc")
})
In some cases parameters idEMGroup o companyId can be null which generates sql looking like this IdEmCompany = 200630758) AND (IdEMGroup = NULL) and it is incorrect sql syntax is it possible to dynamically if value is null for it as 'Column IS NULL' instead of 'Column = NULL' without adding a lot of if's, or it's just better to rewrite this query using Criteria API and just check if value is present and add predicates on certain conditions ?
Correct answer would be to use CriteriaQuery.
Though it is also possible to construct the query dynamically but manipulating #NamedQuery is not possible or might require stuff that makes it not worth to do.
Instead you could construct the query first as a String and create TypedQuery by manipulating the query string
String strQuery = "SELECT i FROM Item i"; // .. + the rest of stuff
if(null==companyId) {
// add something like "companyId IS :companyId"
// ":companyId" coulöd also be NULL"
// but to enable using tq.setParameter("companyId", companyId)
// without checking if there is param "companyId" so there always will
} else {
// add something like "companyId=:companyId"
}
TypedQuery<Item> tq = entityManager.createQuery(strQuery, Item.class);
tq.setParameter("companyId", companyId);
There will be some IFs but so will be in CriteriaQuery construction also.

Setting ORDER BY and LIMIT clause on JPA Query

I'm very, very new to Hibernate and JPA. I want to be able to apply ORDER BY and LIMIT clauses to a Hibernate(?) query, but am coming up empty. NOTE: I inherited this code.
Here is the current code:
public SomeCoolResponse getSomeCoolResponse(String myId) {
String queryString = "select aThing from AWholeBunchOfThings aThing " +
"join aThing.thisOtherThing oThing join oThing.StillAnotherThing saThing " +
"where saThing.subthing.id = :id";
Query q = getEntityManager().createQuery(queryString);
q.setParameter("id", myId);
List<MyThings> list = q.getResultList();
if(list.size() > 0) {
return list.get(0);
}
return null;
}
Instead of getting an entire list and then just returning the first result (which is the only one we need), I'd like to be able to apply a LIMIT 0,1 clause so that the query will be faster. Also, the query needs to be sorted descending on aThing.created which is a UNIX timestamp integer.
I've tried altering queryString like this:
String queryString = "select aThing from AWholeBunchOfThings aThing " +
"join aThing.thisOtherThing oThing join oThing.StillAnotherThing saThing " +
"where saThing.subthing.id = :id ORDER BY aThing.created LIMIT 0,1";
But Hibernate still returns the entire set.
I've looked at using the JPA CriteriaBuilder API, but it hurt my brain.
I'm a total n00b when it comes to this, and any help is greatly appreciated!
I think you need
q.setMaxResults(1);
See also the accepted answer here.
How do you do a limit query in HQL?
As to the "order by" clause you may include it in the queryString.
The JPQL equivalent to LIMIT start,max is:
setFirstResult and setMaxResults:
q.setFirstResult(start);
q.setMaxResults(limit);

JPQL and clausole IN, not found

i have the following situation:
In the dao class:
...
Query q = em.createNamedQuery("myQuery");
q.setParameter("attr", "value");
List<MyObj> listMyObj = q.getResultList();
...
In my file orm.xlm, i defined this query:
<named-query name="myQuery">
<query><![CDATA[
select m from MyEntity1
where id_est in (select mm.id from MyEntity2 where mm.id_est = :attr)
]]></query>
</named-query>
Everything works, there are no configuration problems and / or code, but this query returns 0 elements, when execute the same query in sql returns items expected . Why? There is something i ignore in JPQL?
In this case, if mm.id_est is a String when you set parameter don't use
" 'value' "
but use
" value "
...this was my problem. Fortunately, thanks to this post I realized that in my code I had written as I wrote here on StackOverflow

How to build JPQL queries when parameters are dynamic?

I wonder if there is a good solution to build a JPQL query (my query is too "expressive" and i cannot use Criteria) based on a filter.
Something like:
query = "Select from Ent"
if(parameter!=null){
query += "WHERE field=:parameter"
}
if(parameter2!=null) {
query += "WHERE field2=:parameter2"
}
But i would write WHERE twice!! and the casuistic explodes as the number of parameter increases. Because none or all could be null eventually.
Any hint to build these queries based on filters on a proper way?
select * from Ent
where (field1 = :parameter1 or :parameter1 is null)
and (field2 = :parameter2 or :parameter2 is null)
Why can't you use a criteria, like this.
Other options (less good imho):
Create two named queries one for each condition, then call the respective query.
Or build up a string and use a native query.
Oh, do you just mean the string formation(?) :
query = "Select from Ent where 1=1 "
if(parameter!=null){
query += " and field=:parameter"
}
if(parameter2!=null) {
query += " and field2=:parameter2"
}
(I think that string formation is ugly, but it seemed to be what was asked for)

Categories

Resources