getresultlist - query ok but data duplicate in List - java

I have a problem with getResultList().
My query is OK when it's executed and return 700 results.
In the return List, I had 700 results but the list contains duplicate data.
So I do not have all results.
public List<EscaleCatalogueKaravel> obtenirListeEscaleKaravelSelonMarche(Integer refMarche, Integer refLangue) {
List<EscaleCatalogueKaravel> listeEscales = entityManager.createQuery("select distinct p from EscaleCatalogueKaravel p " +
"where p.refMarche=:refMarche and p.refLangue=:refLangue group by idEscale ")
.setParameter("refMarche", refMarche)
.setParameter("refLangue", refLangue)
.getResultList();
if (listeEscales == null || listeEscales.size() == 0) {
return null;
}
return listeEscales;
}
Have you got an idea ?

You're using MySQL, right? Oracle would not execute the query but throw an error instead.
For correct usage of the group by clause you're only allowed to select that rows (or expressions) which are also mentioned in the group by clause. If you select a row which is not in the group by clause, this row might have different values for the members of one group. Which of these values the database should return? MySQL arbitrarily returns one of the possible values, but that is not correct.
In your query you either only do select distinct idEscale from ... or you group by all necessary columns and only select that ones or you drop your group by clause. By the way, distinct also can be used without group by, and distinct only should be used if really necessary because it makes the query slow.

Related

Convert HQL query in the form of "select foo from Foo foo, Bar bar where ..." to Criteria query

In our (ancient) project, we use loads of select queries with HQL on Hibernate version 3.5.6-Final. Because Hibernate will do an auto-commit, because it doesn't know they are select queries, I'm in the process of rewriting all HQL select queries to Hibernate Criteria queries so it won't do in-between commits when we don't want it yet. This is pretty straight-forward in most cases, but I'm currently looking at a query like this, and I'm not sure how to transform it:
Query query = session.createQuery("select municapilityStreet"
+ " from MunicapilityStreet munStreet, Street street"
+ " where munStreet.id = street.MunicapilityStreet.id"
+ " and street.id = :streetId");
query.setParameter(":streetId", streetId);
MunicapilityStreet result = (MunicapilityStreet) query.uniqueResult();
return result;
Here what I have thus far in the process of transforming it:
Criteria criteria = session.createCriteria(MunicapilityStreet.class);
// No idea what to set here to only get the "municapilityStreet" as result
criteria.setProjection(??);
// I'm not sure if this is correct. With a criteria on a single table it would have been simply "Id".
// Both tables have the column-name Id, and I'm not sure how to differentiate between them.
criteria.add(Restrictions.eq("Street.Id", streetId));
MunicapilityStreet result = (MunicapilityStreet) criteria.uniqueResult();
return result;
Maybe I should create a different question for each, but converting the above HQL query to a Criteria has three points I'm not sure about how to do:
How to do a select with multiple tables (the from MunicapilityStreet munStreet, Street street part)?
How to have a projection to only return a single table of the two (the select municapilityStreet part)?
How to have an equal-Restriction on a column name of one table, even though both tables have the same column-name (the and street.id = :streetId part)?
I do oppose the rewrite approach, I hope I'm not impolite doing so.
Hibernate allows to control commits (autocommit is by default off), and what you're experiencing are Entitymanager-flushes, they are auto by default and can be disabled too. And, finally, I think, there is no difference if you're running HQL or criteria queries, same machinery underneath.

Query to get record of most recent date

I want to fetch the record from DB on basis of most recent date (latest date).
I have written one query down below which is not working and showing error :
11:55:05 select firstName,lastName from mb_orderhistory where
eventType="PROPOSED_ITEM_EDIT" and orderId=80822 and
MAX(updatedDate) GROUP BY orderId Error Code: 1111. Invalid use of
group function 0.015 sec
This is the query which i have written.
select firstName,lastName from mb_orderhistory where eventType="PROPOSED_ITEM_EDIT" and
orderId=80822 and MAX(updatedDate) GROUP BY orderId;
You can't use an aggregate (aka group) function — like MAX — in a WHERE clause. That's because the WHERE clause is evaluated against every possible row, whereas the aggregate function's value is only defined after you've seen all of the matching rows.
See MySQL's docs on SELECT syntax, and specifically:
In the WHERE expression, you can use any of the functions and operators that MySQL supports, except for aggregate (summary) functions.
Instead, you should just order by the updateDate (in descending order, such that the first row that's outputted is the greatest), and use LIMIT to get only one row:
SELECT ... WHERE orderId=80822 ... ORDER BY updatedDate DESC LIMIT 1
(A GROUP BY on a column doesn't make much sense if you also have an equality predicate on that column (orderId=80822). The predicate means that you will only have one group, and you'll know its value: in this case, 80822. The whole purpose of a GROUP BY is to identify groups; if you already know the group, you don't need it.)
In SQL Server, you can use order by like select top 1 firstname,lastname from <table_name> where <condition> order by updateddate desc
You could try:
select
firstName
,lastName
from mb_orderhistory
where eventType = "PROPOSED_ITEM_EDIT"
and orderId = 80822
and updateDate = (select max(updateDate) from mb_orderhistory where eventType = "PROPOSED_ITEM_EDIT" and orderId = 80822)
Select firstName,lastName
From mb_orderhistory
where eventType="PROPOSED_ITEM_EDIT"
and orderId=80822
and updatedDate = (SELECT MAX(updatedDate) FROM mb_orderhistory)
GROUP BY orderId;
This might be helpful to you! Tx.

HQL : The column must appear in GROUP BY or in Select

I've this query with WrappedBean :
buffer.append("SELECT new myPackage.WrappedBean(E.debitant.id, E.dateCalcul, E.verse, E.incidenceReprise, E.soldeSoumission) ");
buffer.append("FROM " + getEntityClassName() + " E ");
buffer.append("LEFT JOIN E.debitant DT ");
buffer.append("WHERE E.debitant.id = :idDebitant ");
buffer.append("AND YEAR(E.dateCalcul) = :year ");
buffer.append("GROUP BY E.debitant.id");
hqlQuery = session.createQuery(buffer.toString());
hqlQuery.setInteger("idDebitant", idDebitant);
hqlQuery.setInteger("year", year);
I've created WrappedBean for returning somme columns and for using Group BY.
When i try to execute it, i obtain this error :
org.postgresql.util.PSQLException: ERREUR: The column « complement0_.date_calcul » must appear in GROUP BY clause or must be used in Select (i translate the error from french)
My POSTGRES query doesnt contain date_calcul in Group BY.
Another problem, in my query i've also this :
SUM(CASE WHEN YEAR(dateCalcul)=#PECAnnee AND verse>0 THEN verse ELSE 0 END)
I know in HQL, we cant do case when in select, for this reason, i dont add SUM to column verse
What i've forgot ?
My POSTGRES query doesnt contain date_calcul in Group BY
That's the problem and what Postgres is complaining about. Why isn't it in the SQL query? Because it isn't in the HQL query. Any column that is selected without the use of some aggregate method like sum(), min(), max() etc. needs to be part of the GROUP BY clause since otherwise the DB doesn't know how to handle multiple values/conflicts.
As an example, what value of E.dateCalcul should be passed to WrappedBean if there are multiple debitors (debitants) (which is most probably the case since otherwise there wouldn't be any need for the GROUP BY clause)?
So to fix this either use
GROUP BY E.debitant.id, E.dateCalcul, E.verse, E.incidenceReprise, E.soldeSoumission
or use aggregate functions, e.g.
WrappedBean(E.debitant.id, max(E.dateCalcul), min(E.verse), max(E.incidenceReprise), sum(E.soldeSoumission))

jpa native query not returning all values

I am using jpa native query , but its not returning values from salias it returns values from S
Query query = em.createNativeQuery("Select S.\"MESSAGE\",S.\"DESTINATION\",S.\"SENT_DATE\",S.\"CLIENT_TRACKING_ID\",S.\"MESSAGE_COST\",S.\"sTId\",salias.\"STATUS\",salias.timeDate from \"sent_sms_view\" S left join ( Select Distinct on (\"SMS_ID\") R.\"SMS_ID\",R.\"STATUS\",R.timeDate from \"sms_receipt_view\" R Order By R.\"SMS_ID\",R.timeDate Desc)As salias on S.\"SYSTEM_TRACKING_ID\"=salias.\"SMS_ID\" where S.Id_systemUser=:systemUser and S.\"CLIENT_TRACKING_ID\"=:cTId");
query.setParameter("cTId", cTId);
query.setParameter("systemUser", systemUser);
if (query.getResultList().size() > 0){
List<Object> resultat = query.getResultList();
This is the Postgres query and it works fine
Select S."MESSAGE",S."DESTINATION",S."SENT_DATE",S."CLIENT_TRACKING_ID",S."MESSAGE_COST",S."sTId" ,salias."STATUS",salias.timeDate
from "sent_sms_view" S
left join ( Select Distinct on ("SMS_ID") R."SMS_ID",R."STATUS",R.timeDate from "sms_receipt_view" R Order By R."SMS_ID",R.timeDate Desc)As salias
on S."SYSTEM_TRACKING_ID"=salias."SMS_ID"
where S.Id_systemUser='101' and S."CLIENT_TRACKING_ID" ='abda';
Can anyone tell me what i am doing wrong.
I'm only guessing what you might be trying to do, since you haven't told us, but here's how I'm guessing it should probably look like:
SELECT S."MESSAGE", S."DESTINATION", S."SENT_DATE", S."CLIENT_TRACKING_ID", S."MESSAGE_COST", S."sTId", salias."STATUS", salias.timeDate
FROM "sent_sms_view" S
INNER JOIN "sms_receipt_view" AS salias on (S."SYSTEM_TRACKING_ID" = salias."SMS_ID")
WHERE S.Id_systemUser=:systemUser AND S."CLIENT_TRACKING_ID"=:cTId
However I don't see why you would have numerical IDs, such as Id_systemUser stored as strings. In fact that variable name indicates horrible database design. CamelCasing combined with underscores is something you must categorically avoid.
And you must never call query.getResultList() twice if you're looking for the same results. Simply store the List to a local variable and then use it.

How to use update hibernate query using setMaxResults?

I hope it is the appropriate section, I have a problem with this code
Transaction transaction = session.beginTransaction();
Query query = session.createQuery("update database set floop= :ctrl1" +" where ctrl= :ctrl2 ").setMaxResults(2);
query.setMaxResults(2);
query.setParameter("ctrl1",3);
query.setParameter("ctrl2", 5);
I ask through setMaxResults(2) to do the update only on the first two and he makes the update of all records as I do what is wrong?? thanks for any help
I thought to use session.createSQLQuery, but I do not know how to do.
This answer is posting delay but it can be helpful for others user who is looking update number of rows in DB with limit using HQL
Unfortunatly setMaxResults() do not work update and delete hibernate
query. It works only select criteria.
As per HQL there is no specific solution is available and you want to update rows with number of limit then follow below steps
Write a HQL to select all rows with condition or range with
setMaxResults. It will return you a List object with limit.
Then update the specific property (Property you want to update) and
store Objects of these rows again by session.update() method.
I'm assuming tablename with map Database class and there are two variable ctrl and floop with getter and setter(as per your question)
List<Database> list = new ArrayList<>();
Transaction transaction = session.beginTransaction();
//Fetching record with limit 2 using setMaxResults()
int setlimit = 2;
String hql_query = "from Database where ctrl = :ctrl2";
Query select_query = session.createQuery(hql_query).setMaxResults(setlimit);
select_query.setParameter("ctrl2", 5);
list = select_query.list();
//iterating list and setting new value to particuler column or property
int result;
if (list != null) {
for (Database element : list) {
element.setFloop(ctrl1);
//Here is updating data in database
session.update(element);
}
result = list.size();
} else {
result = 0;
}
System.out.println("Rows affected: " + result);
transaction.commit();
setMaxResults limits the number of results which are returned by the query, not the number of affected rows.
When you only want to update a limited set of rows, you should specify these rows within the where condition. Setting a hard limit on the number of updated rows wouldn't make much sense, because there would be no way to tell which rows would be updated.
query.setMaxResults(2); will be used for selection queries and will be ignored for insertion/updation. If you use it for selection queries, then you will get 2 records in result.
setMaxResults only applies to select. For your problem I would perform a select query and then use the query.setMaxResults(2), this will return a list of max 2 elements. Then loop the list returned and use session.update for the one or two elements returned.
I can see a number of perfectly valid use-cases where you want to update only a limited number of rows and as other have already answered, the Hibernate Query cannot deal with this so you need to resort to native SQL.
You don't specify in the question which type of database you are using so this answer will only apply to MySql:
Transaction transaction = session.beginTransaction();
Query query = session.createSQLQuery("UPDATE database SET floop= :ctrl1 WHERE ctrl= :ctrl2 LIMIT :max");
query.setParameter("ctrl1",3);
query.setParameter("ctrl2", 5);
query.setParameter("max", 2);
Please note that the sql query above needs to use the native table and column names and not the ones in your ORM model.

Categories

Resources