Null in HQL Expressions - java

I want to know if HQL expressions are null-safe or not?
For example, consider this named query
SELECT a
FROM A a
where a.f=:f
in which f is a field of type String, Double, Date, etc.
Then I use it like:
session.getNamedQuery("myNamedQuery").setString("f", myFValue).uniqueResult();
If both a.f and myFValue are null I want the condition to be true and if just one of them is null I want it to be false.
If it is not null-safe, how can I handle that?
Regards

No, they aren't null-safe. They're translated directly to SQL, and obey the same rules. So if yo want to test for null, you must use is [not] null.
So if the f parameter can be null, you'll have to use two different HQL queries, or build it dynamically, or use a Criteria query to build a dynamic query.

They are not. Try these scenarios out to handle your specific case:
select a from A a where ((:f is null and a.f is null) or a.f = :f) and ...
If your parameter String is null then the query will check if the row's status is null as well. Otherwise it will resort to compare with the equals sign.
If you needed to skip the :status where_clause altogether; you can code like so:
select a from A a where (:f is null or a.f = :f) and ...
This second query is equivalent to:
if(status != null){
sql.append(" a.f = :f and ");
}

You should use is null or is not null.
See HQL "is null" And "!= null" on an Oracle column

They are not null safe.
HQL translates your HQL query to SQL and then it substitute your parameters.SO it won't rewrite query from param = ? to param is null.
Go for Criteria API and use Restrictions.isNull("f");

They are not null safe. Using criteria this would do the trick
public static void addNullSafeEqualsRestriction(Criteria criteria, String propertyName, Object object) {
if (object == null) {
criteria.add(Restrictions.isNull(propertyName));
} else {
criteria.add(Restrictions.eq(propertyName,object));
}
}

Related

JOOQ "IN" Query throws null pointer exception

When we try to fetch data with Null values
field(TABLE_NAME.COLUMN_NAME.in(null))
with IN clause
getting null pointer exception.
Maybe because of this.
#Override
public final Condition in(Collection<?> values) {
Field<?>[] fields = new Field[values.size()];
Iterator<?> it = values.iterator();
for (int i = 0; it.hasNext(); i++)
fields[i] = Tools.field(it.next(), this);
return in(fields);
}
In the database, we can provide null in IN clause.
There is an existing "won't fix" issue in jooq https://github.com/jOOQ/jOOQ/issues/3867
There are some alternatives:
check null before IN(Cant do in my case its a really big select statement)
So if I want to make this possible is there any other workaround.
PS: On a similar note "eq" works perfectly fine:
#Override
public final Condition equal(Field<T> field) {
return compare(EQUALS, nullSafe(field, getDataType()));
}
Edit: 'field(TABLE_NAME.COLUMN_NAME.in(null))' here null is a collection.
Your example code doesn't compile:
TABLE_NAME.COLUMN_NAME.in(null)
There are 5 overloads of this in() method in jOOQ 3.14, and as such, you cannot pass the null literal to the in() method. Your real client code may be using a local variable like this:
Collection<?> collection = null;
TABLE_NAME.COLUMN_NAME.in(collection)
There might be a case for when this should behave the same as passing an empty collection, such as Collections.emptyList(), but this isn't what you seem to want. You probably want to pass actual null values inside of that collection, which you can do:
TABLE_NAME.COLUMN_NAME.in(1, null, 2)
But why would you do it? SQL implements three valued logic, meaning that NULL values have no effect in IN predicates, while they have an unintuitive, hardly desired effect in NOT IN predicates (the entire predicate becomes NULL)

How to handle null values in an HQL query when checking a list for a contained integer value

What I have is a Spring Boot repository in which I try to create a query function using HQL.
The function takes an Integer parameter which should be ignored by the query if it is null, else a list should be checked if it contains the value.
I have the where clause in two parts, the null check and the list check, looking like this:
#Query("SELECT u FROM MyEntity " +
" WHERE (:myParam is null or :myParam in (2, 3))"
)
Now the problem is that for the :myParam in (2, 3) part it is complaining "Inconsistent Datatypes: expected BINARY got NUMBER
(when :myParam is null, for :myParam != null it works)
I tried:
casting either the param or the null value to in
using coalesce(:myParam, CAST(NULL AS int)) which worked on a similar problem with :myParam being an integer list
using a switch case statement
(case when :spracheKy is null then true when :spracheKy in (2, 3) then true else false end) = true
Thanks in advance for any help
why don't you just make use of two different repository methods, e.g. one that takes no parameter and another method that takes the parameter. and then decide and encapsulate the decision taking logic in a separate method of your service layer - I mean the logic which repository method to call based on parameter being null or not... could look like this:
#Service
#Transactional
public class YourService {
// autowired by constructor injection
private final YourEntityRepository repo;
public List<YourEntity> getAllYourEntitiesByParam(Long param) {
if (param == null) {
return repo.findAll();
}
return repo.findAllByParam(param);
}
}

How to I remove L from Long field's values in java spring

I put query param for my list services for example:
tablename/list?query=id:10
it is running but I added other param
'personTNo'
tablename/list?query=id:10&personTNo=101035678
id is Integer but personTNo is Long
when I try to this sql returns select * from TABLENAME WHERE personTNo=10L
but this I want to return without 'L' for Long value. It is my code's a bit section in RepositoryCustom class
public List<TABLENAME> getTable(Specification aTablenameSpec) {
CriteriaBuilder builder = mEntityManager.getCriteriaBuilder();
CriteriaQuery<Object> query = builder.createQuery();
Root<TABLENAME> root = query.from(TABLENAME.class);
String queryWhere = null;
org.hibernate.query.Query hibernateQuery = null;
Predicate predicate = aTablenameSpec.toPredicate(root, query, builder);
if (predicate != null) {
query.where(predicate);
query.select(root);
TypedQuery<Object> typedQuery = mEntityManager.createQuery(query);
hibernateQuery = typedQuery.unwrap(org.hibernate.query.Query.class);
String queryString = hibernateQuery.getQueryString();
This row returns with L result, How to remove 'L' value in sql
Use INTEGER() function in the sql query. You can also try CAST() or CONVERT() functions in the query
Based on the problem description and code, it seems safe to assume the tech stack includes: JPA and Spring Data JPA.
And I understand that you want to remove the Long value L suffixes, but it's not clear if that's because the suffixes are causing a problem or exactly why you want the suffixes removed.
I only say that because the example query string appears to be a valid JPA query:
select * from TABLENAME WHERE personTNo = 10L
JPA support for the use of literal values in queries includes support for standard Java numeric (integer/long/float/double) literal value syntax.
Which means the L suffix on the literal Long value of personTNo, as defined in your query (10L), is legitimate, valid, and should not cause a problem.
Please let me know if I've missed the point, made an incorrect assumption, or overlooked something, and I will follow up.

Hibernate restriction in causes an error if the list is empty

If my list is empty, I get the following error:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')'
Below is my hibernate related method:
#Override
public List<SomeThing> findByIds(List<Integer> someIds) {
return sessionFactory.getCurrentSession().createCriteria(SomeClass.class)
.add(Restrictions.in("id", someIds))
.list();
}
What should I do to guard against this error?
I know I could short-circuit the call and return an empty list like:
if(someIds == null || someIds.size() == 0) {
return new List<SomeThing>();
}
But is there a more elegant way to do this?
I would say Hibernate needs to fix this issue, and give meaningful message.
I think its responsibility of the provider/hibernate to check for the empty/null List.
One can imagine the cause, it tries to construct where clause, something like id in (), somewhere in org.hibernate.loader.criteria.CriteriaQueryTranslator or similar..But because here the List is empty, it would be throwing an exception. But they already created query with ( and could not complete because of exception/empty List.
NO. If you execute the query with empty parameters for in clause, it will fail (you may verify this by running plain SQL). Better not to execute the query if the input param is null/empty.
Only thing I can advice is to use isEmpty() function and != null in if statement and little restructuring as:
#Override
public List<SomeThing> findByIds(List<Integer> someIds) {
List<Something> result = null; //you may initialize with empty list
if(someIds != null || !someIds.isEmpty() {
result = sessionFactory.getCurrentSession().createCriteria(SomeClass.class)
.add(Restrictions.in("id", someIds))
.list();
}
return result;
}
(This is mostly base on #Yogendra Singh's reply, with a twist to make it more adoptable to commonly-seen situation of multiple optional argument)
Criteria API aims to let you compose your query programmatically. Such kind of dynamic feature is expected to be handled in your code.
Normally we make optional criteria by this:
#Override
public List<SomeThing> findBySearchParams(SearchParam searchParam) {
// create criteria with mandatory search criteria
Criteria criteria = sessionFactory.getCurrentSession()
.createCriteria(SomeClass.class);
.add(Restriction("someField", searchParam.getSomeField()));
// add "id" only if "someId" contains value
if(searchParam.getSomeIds() != null && !searchParam.getSomeIds().empty()) {
criteria.add(Restrictions.in("id", searchParam.getSomeIds()));
}
// add "anotherField" only if "anOptionalField" is not null
if(searchParam.getAnOptionalField() != null) {
criteria.add(Restrictions.in("anotherField", searchParam.getAnOptionalField()));
}
return criteria.list();
}
Edit:
Although Hibernate does not (yet) provide a more elegant way for that, you can write something yourself to make it looks more elegant:
class SmartCriteriaBuilder {
private Criteria criteria;
SmartCriteriaBuilder (Criteria criteria) { this.criteria = criteria;}
SmartCriteriaBuilder in(String field, Collection values) {
if (!empty(values)) {
this.criteria.add(Restrictions.in(field,values));
}
}
// all other kind of restrictions ....
Criteria toCriteria() {
return this.criteria;
}
}
Then you can do something looks smarter:
SmartCriteriaBuilder criteriaBuilder =
new SmartCriteriaBuilder(sessionFactory.getCurrentSession().createCriteria());
criteriaBuilder .in("someField", listPossiblyNullOrEmpty);
return criteriaBuilder .toCriteria().list();

issue dealing the ResultSet Value in Eclipse Rcp

My ResultSet Query is
StrQry = "select SUM(isnull(prn_amount,0))as prn_amount,SUM(isnull(adv_prn,0))as adv_prn, SUM(isnull(prv_prn,0))as prv_prn from loan_transaction_mcg where loan_id='1117'";
It is giving the result as on Sql
prn_amount =NULL
adv_prn =NULL
prv_prn =NULL
when the loan id =1117
ResultSet RsPrincipalDetail = getPaidDetail(loan_id);
while(RsPrincipalDetail.next()){
prn1 = RsPrincipalDetail.getString("prn_amount");
prn2 = RsPrincipalDetail.getString("adv_prn");
prn3 = RsPrincipalDetail.getString("prv_prn");
if(prn1.equals("")){
prn1.equals("0");
}
if(prn2.equalsIgnoreCase("")){
prn2.equals("0");
}
if(prn3.equalsIgnoreCase("")){
prn3.equals("0");
}
I tried putting prn1.equals(null) but still the null pointer exception comes. I tried in debug mode on prn1, it is showing as null as its value.
The problem here is that since your values in database are NULL when you convert them to java values using getString they will also be null.
Since null is not the same as empty string you can not really use prn.equals("")
Also using prn.equals(null) is a bad idea as usually the way that equals is implemented ... it will return false if something that it is compared to is null
Your best bet is to use equality operator to check for null
if(prn == null)
What are the column names of the table?
For me this seems to be possibly cyclic:
SUM(isnull(prn_amount,0))as prn_amount
and there seems to be a group by missing in your statement on loan_id

Categories