Response json not equals to sql query - spring-boot

I need the user id, user name, asesor nombre, asesor telefono, asesor correo and the tipo asesor but the json response repeat data.
this is the sql query in the spring reposotiry.
'''
#Query( value = "SELECT U.id as userid, u.name as cliente," +
"A.nombre, A.correo, A.telefono, TA.tipo as asesoria " +
"from tc_users U, tc_usuario_asesores UA , " +
"tc_asesor A,tc_tip_asesor TA " +
"where U.id = UA.userid " +
"and UA.asesorid= A.id " +
"and A.tipo_asesor = TA.id",
nativeQuery = true)
'''
and this query in sql workbench return this data
query in sql workbench
but the json response return this data
Json response
and dont know because this haappend, a need help with this, sorry for my bad inglish.

Your query returns a cartesian product because of the join.
You can add DISTINCT to get unique rows.
#Query( value = "SELECT DISTINCT U.id as userid, u.name as cliente," +
"A.nombre, A.correo, A.telefono, TA.tipo as asesoria " +
"from tc_users U, tc_usuario_asesores UA , " +
"tc_asesor A,tc_tip_asesor TA " +
"where U.id = UA.userid " +
"and UA.asesorid= A.id " +
"and A.tipo_asesor = TA.id",
nativeQuery = true)

Related

JPA #Query SpEL throwing EL1007E despite null checks

I have this query:
#Query(value =
"select distinct t from TimesheetReport t "
+ "where t.month = :month and t.year = :year and t.approvedByMaster = false "
+ "and (:#{#rule.employee} is null or :#{#rule.employee.id} is null "
+ "or t.account.id = :#{#rule.employee.id}) "
+ "and t.id in "
+ "(select distinct dt.timesheetReport.id from DailyTime dt "
+ "where (:#{#rule.project} is null or :#{#rule.project.id} is null "
+ "or dt.project.id = :#{#rule.project.id}) "
+ "and (:#{#rule.client} is null or :#{#rule.client.id} is null "
+ "or dt.client.id = :#{#rule.client.id})) "
+ "or t.id in "
+ "(select distinct cdt.timesheetReport.id from CustomDailyTime cdt "
+ "where (:#{#rule.project} is null or :#{#rule.project.id} is null "
+ "or cdt.project.id = :#{#rule.project.id}) "
+ "and (:#{#rule.client} is null or :#{#rule.client.id} is null "
+ "or cdt.client.id = :#{#rule.client.id}) "
+ ")"
)
Set<TimesheetReport> findTimesheetsMatchingManualApprovalRule(LeaderManualApprovalRulesDTO rule, int month, int year);
I know this is caused by employee object being null.
This happens despite first checking if employee in rule is null and then checking if employee object id field is null. I still get "Property or field 'id' cannot be found on null".
Is it because SpEL needs to be able to evalute every parameter before firing a query?

org.postgresql.util.PSQLException: ERROR: argument of AND must be type boolean, not type record

#Query(value = "SELECT DISTINCT * " +
"FROM chores WHERE id in (SELECT a.id " +
"FROM chores as a INNER JOIN chores_assign_users as b ON a.id=b.chore_id " +
"WHERE (a.is_deleted=FALSE " +
"AND a.family_id=:familyId " +
"AND (:userId IS NULL OR (cast(b.user_id as VARCHAR) IN :userId)) " +
"AND (:status IS NULL OR (a.status IN :status)) " +
"AND (:title IS NULL OR a.title LIKE cast(:title as text)) " +
"AND (:from IS NULL OR :to IS NULL OR cast(created_at as VARCHAR) >= :from AND cast(created_at as VARCHAR) <= :to)) " +
"ORDER BY :sortByDeadline" +
", CASE WHEN :sortByDeadline THEN a.deadline END DESC " +
", CASE WHEN NOT :sortByDeadline THEN a.created_at END DESC)",
countQuery = "SELECT COUNT(DISTINCT a.id) FROM chores as a INNER JOIN chores_assign_users as b ON a.id=b.chore_id " +
"WHERE a.is_deleted=FALSE " +
"AND a.family_id=:familyId " +
"AND (:userId IS NULL OR (cast(b.user_id as VARCHAR) IN (:userId))) " +
"AND (:status IS NULL OR (a.status IN (:status))) " +
"AND (:title IS NULL OR a.title LIKE cast(:title as text))" +
"AND (:from IS NULL OR :to IS NULL OR cast(created_at as VARCHAR) >= :from AND cast(created_at as VARCHAR) <= :to)) ",
nativeQuery = true)
ArrayList<Chore> findAlLFilteredByUserAndStatusAndTitleSortedByCreatedAtOrDeadLine(#Param("familyId") int familyId,
#Param("userId") List<String> userId,
#Param("status") List<String> status,
#Param("title") String title,
#Param("sortByDeadline") boolean sortByDeadline,
#Param("from") String from,
#Param("to") String to,
Pageable pageable);
I have this native query in a jpa repository. As you can see, I search for the records which have user_id IN :userId. This works fine as long as userId contains only one element. But if userId contains more than one element, this exception will be thrown org.postgresql.util.PSQLException: ERROR: argument of AND must be type boolean, not type record. The same problem happens to "AND (:status IS NULL OR (a.status IN :status)) "
user_id has type integer
status has type varchar
I am having a hard time finding a way to fix this. Could you please help me with this? And also, is it good to pass a List of integers to the query as a list of string by converting every elements to string just like I do with userId in this case? Can it be the problem and how can I fix it? Thank you for your time!
org.postgresql.util.PSQLException: ERROR: argument of AND must be type boolean, not type record. The same problem happens to "AND (:status IS NULL OR (a.status IN :status)) "
I think using COALESCE(:status) IS NULL instead of :status IS NULL will solve above problem.

linq condition in select statement

I have a linq query
from c in db.Custommer
join m in db.Membership on c.ID equals m.CustomerID
select (c.LastName + ", " + c.FirstName + " " + c.MiddleName);
The MiddleName could be NULL, how do I replace that null with a space or ignore it?
If I leave it this way, the query does not return any records for customers who don't have middle names.
You can do as such:
from c in db.Custommer
join m in db.Membership on c.ID equals m.CustomerID
select (c.LastName + ", " + c.FirstName + " " + (c.MiddleName ?? "");
This should do the trick :)

Pass date parameter to native query

A user can perform actions based on an occurrence value. When this value is equal to 'DAILY', I would like to retrieve all daily actions that have not been completed the last 24 hours.
The working SQL query:
SELECT distinct a.* FROM action as a LEFT OUTER JOIN history as h
ON a.id = h.action_id
AND h.user_id= <user> WHERE a.occurrence = 'DAILY' AND (h.id is NULL OR h.entry_date < TIMESTAMP 'yesterday')
The equivalent native query:
#Query(value =
"SELECT distinct a.* FROM action a "
+ "LEFT OUTER JOIN history h "
+ "ON a.id = h.action_id "
+ "AND h.user_id = :userId "
+ "WHERE a.occurrence='DAILY' AND (h.id IS NULL OR h.entry_date < :yesterday) ", nativeQuery = true)
public List<Action> findAllAvailableActions(#Param("userId") Long userId, #Param("yesterday") ZonedDateTime yesterday);
How it is called in my service :
ZonedDateTime today = ZonedDateTime.now(ZoneOffset.UTC);
ZonedDateTime yesterday = today.minus(1,ChronoUnit.DAYS);
Long userId = userDTO.getId();
List<Action> result = actionRepositoryCustom.findAllAvailableActions(userId, yesterday);
However, I do get the wrong results in my tests (actions that have already been completed are returned). I am afraid this is linked to the date parameter. The attribute entry_date is declared as ZoneDateTime in my entity. What am I doing wrong ?
hibernate : 5.2.4
You can't pass a ZonedDateTime into a native SQL query. You need to convert it to Calendar:
#Query(value =
"SELECT distinct a.* FROM action a "
+ "LEFT OUTER JOIN history h "
+ "ON a.id = h.action_id "
+ "AND h.user_id = :userId "
+ "WHERE a.occurrence='DAILY' AND (h.id IS NULL OR h.entry_date < :yesterday)", nativeQuery = true)
public List<Action> findAllAvailableActions(#Param("userId") Long userId, #Param("yesterday") Calendar yesterday);
And you can convert your ZonedDateTime this way:
public Calendar convertToDatabaseColumn(ZonedDateTime entityAttribute) {
if (entityAttribute == null) {
return null;
}
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(entityAttribute.toInstant().toEpochMilli());
calendar.setTimeZone(TimeZone.getTimeZone(entityAttribute.getZone()));
return calendar;
}
This approach is described here: link

jpql native query not setting parameter

#Repository
public interface GroupRepository extends JpaRepository<Group, String> {
//Other queries....
#Query(value = "with cte(group_id, parent_group_id, group_name) as( "
+ "select group_id, parent_group_id, group_name "
+ "from hea.hea_group "
+ "where group_id = ?1 "
+ "union all "
+ "select g.group_id, g.parent_group_id, g.group_name "
+ "from hea.hea_group g "
+ "inner join cte on cte.group_id = g.parent_group_id "
+ "where g.parent_group_id is not null "
+ ") select * from cte", nativeQuery = true)
List<Object> getChildGroups(String groupId);
}
Above is the query that I have written that should return the parent group and all of its children. The query does what it is suppose to do when I replace the ?1 with a hard coded group id value and change the method to have no parameters, but when I try to run it as above it returns nothing even though I'm passing in the exact same value that I was hard coding.
Below is the sql that is being generated by the query. When I replace the ? with a group id an run it on a test database it returns the results that it should.
with cte(group_id, parent_group_id, group_name) as( select
group_id,
parent_group_id,
group_name
from
hea.hea_group
where
group_id = ?
union
all select
g.group_id,
g.parent_group_id,
g.group_name
from
hea.hea_group g
inner join
cte
on cte.group_id = g.parent_group_id
where
g.parent_group_id is not null ) select
*
from
cte
The variables are zero based so ?0 is what you should use.

Resources