Query annotation not working for max(id) - spring-data

I have a domain object GenJournal and it has an "id" member (Long) that's auto-generated. I also have a JPA repository that I've added ...
#Query("select coalesce(max(u.id), 0) from GenJournal u")
Long getMaxId();
The method getMaxId() returns zero or null before I added coalesce. I have two rows in my database with ids 1 and 2. Can anyone help me determine why this doesn't work?
I'm trying to get the latest or max id so that I can use the find method after to return the most recent GenJournal object in my service class.
I'm stumped and really need some options or strategy to determine why this doesn't work.

You could use "Native Query" feature by passing nativeQuery = true param into #Query annotation like this
#Query("select coalesce(max(u.id), 0) from Gen_Journal_Table u", NativeQuery = true)
Long getMaxId();

My issue was two-fold. First I was getting null without the use of "coalesce". That caused me to think that this didn't work. When I adopted the use of "coalesce" I didn't realize that my table had no records and was returning the zero (0). My table in the production profile did have two records and I was expecting an id of 2.
I was manually checking the wrong database and setting expectations that were incorrect.

Related

SQL Error: 0, SQLState: 42703 with message "The column name str_id was not found in this ResultSet"

this is my first question ever in StackOverflow and as suggested, I have looked at other similar questions and attempted to use their responses for my problem. So far, no luck.
The situation is as follows:
I have a custom query in JPA.
#Query(value="SELECT u.str_id,u.str_exercise_name, u.str_target_body_part,u.char_effect FROM training_schema.exercise_entity u WHERE u.str_exercise_name = ?1 and u.str_target_body_part= ?2", nativeQuery=true)
ExerciseEntity findExerciseEntityByNameAndTargetBodyPart(String str_exercise_name,String str_target_body_part);
If I remove the name of the columns (u.str_id, u.str_exercise_name, u.str_target_body_part, u.char_effect) and replace the query with:
#Query(value="SELECT u FROM training_schema.exercise_entity u WHERE u.str_exercise_name = ?1 and u.str_target_body_part= ?2", nativeQuery=true)
ExerciseEntity findExerciseEntityByNameAndTargetBodyPart(String str_exercise_name,String str_target_body_part);
I get the following error:
"The column name str_id was not found in this ResultSet"
The fact that the error doesn't come when I mention all the columns and is generated when I use alias 'u' doesn't make sense because this would mean that if I ever had to work with a larger table with, say, 10 columns, I would have to write them all out.
One more piece of information that hopefully helps: With the version of the query where I am using 'u' instead of the column names, the error is ONLY generated when a matching record is found. For a null return from the database, there is no problem.
Using Java Spring and PostgresSQL.
I was able to figure out the problem.
In the query where I am using the alias 'u' ALONE, I had to make a slight change. Instead of just saying 'u', I changed it to:
#Query(value="SELECT u.* FROM training_schema.exercise_entity u WHERE u.str_exercise_name = ?1 and u.str_target_body_part= ?2", nativeQuery=true)
ExerciseEntity findExerciseEntityByNameAndTargetBodyPart(String str_exercise_name,String str_target_body_part);
Using only 'u', was returning a record set WITHOUT any headers. Adding the '*' caused the query to return a resultset with column names which made the error go away.

Spring Data: Getting NonUniqueResult Problem for the query

Hello experts of the world. Need some help concerning executing a query with SpringData.
The expectation is to execute the Query below in the Spring Data annotation by combining with the repository method name (Automated Query Construction) to get a unique result. Apparently it fails from time to time by saying the result is not Unique.
The question here is if the method name is still considered in Query Construction while also executing the query in the annotation.
#Query("SELECT r from Revision r WHERE r.revisionBid = ?1 AND r.revisionStatusId = ?2 ORDER BY r.lastModifiedDate DESC")
Optional<Revision> findFirst(Integer revisionBid, Integer revisionStatusId);
Thanks in advance!
The query creation for limiting to 1 result is defined here with FIRST & TOP included in the method name.
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.query-methods.query-creation
I don't think "findFirst" will work when you're using an #Query, as the query will be constructed from HQL expression in the #Query rather than the fluent API passing over the method name. Because of this, when the query returns multiple results, it will throw the exception as the Optional is told to wrap a single returned object, not a collection. Add a LIMIT clause to the HQL query and you should be good.

Optional parameters in named query in EclipseLink

I am new to JPA named queries using EclipseLink and I want to "ignore" properties with null values in named query. I know that my question has been answered many times.
e.g. JPA Query to handle NULL parameter value
However, in my case following format is not working
+ " AND (:quoteNumber IS NULL OR ord.quoteNumber = :quoteNumber)"
I am getting error 'ILLEGAL USE OF KEYWORD NULL'. I will be using CriteriaQuery now and just curious why it is not working in named query.
Following are the DB2 and Eclipselink versions being used.
eclipselink: 2.5.1
DB2: DSN11015
The JPA Specification says that
3.8.13 Named Queries
Named queries are static queries expressed in metadata. Named queries can be defined in the Java Persistence query language or in SQL. Query names are scoped to the persistence unit.
So you can't really expect them to change on runtime based on some null condition. Criteria Query, as you point out, is dynamic by nature, so would be the way to go.
EDIT based on comment:
AND (ord.quoteNumber = :quoteNumber or :quoteNumber is null or :quoteNumber = ''
does not change the query on runtime (does not skip the clause). It evaluates the clause as TRUE. The problem with DB2 (and Derby as far as I know) is, that they do not allow "non-typed Null to be sent to the backend" as per API PreparedStatement.setObject. You can test it by setting the type via casting
AND (ord.quoteNumber = cast(:dfdTxt as integer) or cast(:dfdTxt as integer) is null or cast(:dfdTxt as integer) = ''
So this approach is DB Implementation specific and might change at some point.

OrientDB indexes are not working properly with formatted params used in server functions

OrientDB is throwing a java.lang.ClassCastException when a sever function (a query on indexed fields) is executed with formatted params.
Following messages are seen with the exception.
"Error on using index", "Probably you need to rebuild indexes. Now executing query using cluster scan
e.g.
db.query("SELECT FROM Employee WHERE department = ?", departmentRid);
where, Employee.department is indexed with NOT_UNIQUE_HASH_INDEX
When I removed the formatted params and injected them manually index worked out fine.
e.g.
db.query("SELECT FROM Employee WHERE department = " + departmentRid);
Any reason why the first approach didn't work? I'd like to refrain from injecting the params manually.
Note that the both approaches gives me the correct result. The problem is that the index is not applied for the first approach.
I am using orientdb-community-2.1.0
Appreciate your help.
I tried it with version 2.1.0, I have the NOTUNIQUE_HASH_INDEX on department field of Employee and it works

JPQL Group By not working

This is my simple JPQL:
SELECT s
FROM Site s
GROUP BY s.siteType
siteResult = q.getResultList();
for (Site site : siteResult) {
// loops all sites
}
This query returns all sites, including sites of the same siteType.
I'm using JPA 2.0 Eclipselink.
Whats wrong here?
Such a query does not make sense. If you use GROUP BY, other attributes in SELECT should be aggregated. As it is said in JPA specification:
The requirements for the SELECT clause when GROUP BY is used follow
those of SQL: namely, any item that appears in the SELECT clause
(other than as an aggregate function or as an argument to an aggregate
function) must also appear in the GROUP BY clause. In forming the
groups, null values are treated as the same for grouping purposes.
If you think SQL counterpart of your query:
SELECT s.attr1, attr2, s.siteType
FROM site s
GROUP BY (s.siteType)
you notice that it is hard to imagine which possible value of attr1 and attr2 should be chosen.
In such a case EclipseLink with derby just drops GROUP BY away from the query, which is of course little bit questionable way to handle invalid JPQL. I like more how Hibernate+MySQL behaves with such a invalid JPQL, it fails with quite clear error message:
java.sql.SQLSyntaxErrorException: The SELECT list of a grouped query
contains at least one invalid expression. If a SELECT list has a GROUP
BY, the list may only contain valid grouping expressions and valid
aggregate expressions.
Answer to comment:
One Site contains probably also attributes other than siteType as well. Lets use following example:
public class Site {
int id;
String siteType;
}
and two instances: (id=1, siteType="same"), (id=2, siteType="same"). Now when type of select is Site itself (or all attributes of it) and you make group by by siteType, it is impossible to define should result have one with id value 1 or 2. Thats why you have to use some aggregate function (like AVG, which gives you average of attribute values) for remaining attributes (id in our case).
Behind this link: ObjectDB GROUP BY you can find some examples with GROUP BY and aggregates.