How to add a dynamic where in #Query? - spring-boot

I need to add my where conditions based in my filter object. If some value in the filter object is null, isn't necessary add the where condition of this parameter.
How to add a dynamic where?
Exemple:
FilterObject{
name: "Teste";
age: null;
}
#Query(value="SELECT id FROM user WHERE name = FilterObject.name", nativeQuery = true)
public List<User> getUsers(???)
Other example:
FilterObject{
name: "Teste";
age: 12;
}
#Query(value="SELECT id FROM user WHERE name = FilterObject.name AND age = FilterObject.age", nativeQuery = true)
public List<User> getUsers(???)
This is a highlevel example. Isnt the correct code. But... Is the necessary to understand my question
If a parameter of my filter is null this parameter isnt used in my where
Im Using spring boot with Spring Data JPA and my Query stay in my repository a Repository.
My Original request:
#Query(value = " SELECT "
+ " solicitacao.nm_orgao AS nmOrgao, "
+ " solicitacao.ds_ano_exercicio AS exercicio, "
+ " solicitacao.nm_organismo AS nmOrganismo, "
+ " dadosBancarios.valor AS valor, "
+ " dadosBancarios.valor * dadosBancarios.vl_taxa_cambio AS valorReais, "
+ " dadosFinanceiros.vl_dotacao_disponivel AS vlDotacaoDisponivel, "
+ " solicitacao.id_solicitacao AS codigoPagamento "
+ " solicitacao.tp_solicitacao_status AS idFase, "
+ " organismo.id_orgao AS idOrgao, "
+ " solicitacao.id_organismo AS idOrganismo, "
+ " pagamentos.id_status_pagamento AS statusPagamento "
+ " FROM "
+ " tbs_solicitacao solicitacao "
+ " JOIN tbs_dados_bancarios dadosBancarios ON solicitacao.id_solicitacao = dadosBancarios.id_solicitacao "
+ " JOIN tbs_dados_financeiros dadosFinanceiros ON dadosFinanceiros.id_solicitacao = solicitacao.id_solicitacao "
+ " JOIN tbs_organismo organismo ON organismo.id_organismo = solicitacao.id_organismo "
+ " JOIN tbs_pagamentos pagamentos ON dadosFinanceiros.id_dados_financeiros = pagamentos.id_dados_financeiros ",nativeQuery = true)
List<Object[]> getRelatoriosProgramacao();

You can use Spring Data JPA specifications:
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#specifications
You simply have to implement the method toPredicate:
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder);
In this method you get root, query and the CriteriaBuilder to create a Criteria API where predicate.
Event methods like findAll take a Specification.

Related

repeated data in json response spring boot

I have this SQL query
#Query( value = "select tc_users.id as userid,tc_devices.id as deviceid, tc_devices.name, tc_devices.lastupdate as hora_fecha,\n" +
"tc_positions.speed as velocidad, tc_positions.latitude, tc_positions.longitude, tc_positions.devicetime\n" +
"from tc_devices\n" +
"join tc_users on tc_users.id = tc_devices.userid \n" +
"join tc_positions on tc_devices.id= tc_positions.deviceid and \n" +
"tc_positions.devicetime=(select max(devicetime) from tc_positions where tc_positions.deviceid= tc_devices.id) and tc_users.id= ?1 ;", nativeQuery = true)
List<resumen_entity> resu(Integer userid);
This SQL query return this data
result of query in SQL workbench
but when using it with my spring project it returns this json
result of query by springboot
a really need help with this problem
I try with another type of SQL query but spring returns the same result
#Query( value = "select distinct tc_users.id as userid,tc_devices.id as deviceid, " +
"tc_devices.name, tc_devices.lastupdate as hora_fecha, " +
"tc_positions.speed as velocidad, tc_positions.latitude, " +
"tc_positions.longitude, tc_positions.devicetime " +
"from tc_users, tc_devices,tc_positions where tc_users.id =tc_devices.userid " +
"and tc_devices.id= tc_positions.deviceid " +
"and tc_positions.devicetime=(select max(devicetime) " +
"from tc_positions where tc_positions.deviceid = tc_devices.id) and tc_users.id= ?1 ",
nativeQuery = true)
List<resumen_entity> resu(Integer userid);

I use #Query annotation in Jpql, I modified my query with additional "distinct", How to Fix it?

In my Repositories, I modified my query with additional "distinct" and it can't work
#Query(value = "select distinct i from Item i "
+"where i.store = ?1 and i.itemVariant IN ?2 "
+"and i.status = ?3 " )
Page<Item> findByStoreAndItemVariantInAndStatus
(Store store, List<ItemVariant> itemVariant ,byte status, Pageable pageable);
if I remove the additional modifying #Query, this works but the result is duplicated
I have fixed it. I change it using native query and changed distinct to group by, and it's works
#Query(value = "SELECT i.* "
+" FROM public.mst_item as i "
+" join public.mst_store as ist "
+" on i.store_id = ist.id "
+" join public.mst_item_classifiers as iv "
+" on iv.item_id = i.id "
+" where ist.id = :store and iv.name IN "
+" (select ic.name from public.mst_item_classifiers as ic "
+" where ic.name like concat('%',:itemVariant,'%') and ic.status = :status ) "
+" and i.status = :status "
+" group by ?#{#pageable}, i.id",
nativeQuery = true)
Page<Item> findByStoreAndItemVariantInAndStatus(#Param("store")Store store,#Param("itemVariant") String itemVariant , #Param("status") byte status, Pageable pageable);

How to ignore SQL Query part of WHERE conditionally in JPA Query

I am wondering if it is possible to ignore part of query (not whole where part) conditionally. I have query in JPA
#Query("SELECT DISTINCT new it.akademija.wizards.models.document.DocumentGetReviewCommand(" +
"d.author.firstname, d.author.lastname, d.id, d.title, d.description, d.documentType.title, d.submissionDate)" +
" FROM Document d" +
" JOIN d.documentType dt" +
" JOIN dt.reviewUserGroups rug" +
" JOIN rug.users u WHERE u.username = :username" +
" AND d.documentState = it.akademija.wizards.enums.DocumentState.SUBMITTED" +
" AND u <> d.author" +
" **AND (lower(CONCAT(d.author.firstname, ' ', d.author.lastname)) like %:searchFor% " +
" OR lower(d.title) like %:searchFor%" +
" OR lower(d.description) like %:searchFor%" +
" OR lower(d.id) like %:searchFor%" +
" OR lower(dt.title) like %:searchFor%)")
Page<DocumentGetReviewCommand> getDocumentsForReview(#Param(value = "username") String username,
#Param(value = "searchFor") String searchFor,
Pageable pageable);
How can I ignore below part if searchFor param is null or blank ("")
AND (lower(CONCAT(d.author.firstname, ' ', d.author.lastname)) like %:searchFor% " +
" OR lower(d.title) like %:searchFor%" +
" OR lower(d.description) like %:searchFor%" +
" OR lower(d.id) like %:searchFor%" +
" OR lower(dt.title) like %:searchFor%)
You could just try adding logic which allows these conditions to be skipped should the search for term be null or empty:
AND
(COALESCE(:searchFor, '') = '' OR
(LOWER(CONCAT(d.author.firstname, ' ', d.author.lastname)) LIKE %:searchFor% OR
LOWER(d.title) LIKE %:searchFor%" OR
LOWER(d.description) LIKE %:searchFor% OR
LOWER(d.id) LIKE %:searchFor% OR
LOWER(dt.title) like %:searchFor%))

#Query not recognizing parameters if they are inside single quote in Spring Framework

I have a big problem with Spring Data in #Query.
I have the following query :
SELECT created_at::DATE "date",
count(*)
FROM
absence
WHERE
created_at::DATE between '2018-05-27' AND '2018-05-31'
GROUP BY created_at::DATE;
this query works in postgres without any problem now in spring to use it :
#Query("SELECT created_at\\:\\:DATE \"date\",count(*) FROM absence " +
"WHERE created_at\\:\\:DATE between '?1' AND '?2' " +
"GROUP created_at\\:\\:DATE", nativeQuery = true)
fun getAbsenceCount(beginDate: String,endDate: String): List<AbsenceCount>
This query doesn't work at all, the problem is that spring can't recognize the parather beginDate (?1) & endDate (?2).
I tried a lot of solution from stackoverflow like solution and solution 2 but I can't get rid of this problem.
I don't know if it's intented or it's a bug in spring.
Try to simply use the classic SQL cast function:
#Query(value = "" +
"select " +
" cast(a.created_at as date) as createdAt, " +
" count(*) as quantity " +
"from " +
" absence a " +
"where " +
" cast(a.created_at as date) between ?1 and ?2 " +
"group " +
" cast(a.created_at as date)" +
"", nativeQuery = true)
fun getAbsenceCount(beginDate: String, endDate: String): List<AbsenceCount>
where AbsenceCount is a projection like this (java):
public interface AbsenceCount {
LocalDate getCreatedAt();
Long getQuantity();
}

Alias Column In Resultset

I have a query in backend spring project, where I create a field alias named agent_id but I don´t have that column in Model. What is the best approach for showing this as a field in table view in front end???.
Here´s the query:
Query query = em.createNativeQuery("SELECT" +
" ips.*, " +
" s.mls_id AS imported," +
" p.INTEGRATOR_SALES_ASSOCIATED_ID AS agent_id " +
"FROM test1.ilist_property_summary ips " +
" LEFT JOIN test1.statistics s ON s.mls_id = ips.INTEGRATOR_PROPERTY_ID " +
" LEFT JOIN test1.person p ON p.INTEGRATOR_SALES_ASSOCIATED_ID = ips.INTEGRATOR_SALES_ASSOCIATED_ID " +
"WHERE ips.AGENCY_ID = :agencyId AND (s.statistics_type = 1 OR s.statistics_type IS NULL) AND ips.ORIG_LISTING_DATE BETWEEN :startDate AND :endDate");
query.setParameter("agencyId", agencyId)
.setParameter("startDate", DateUtil.asDate(startDate), TemporalType.DATE)
.setParameter("endDate", DateUtil.asDate(endDate), TemporalType.DATE);
return (List<PropertyVO>) query.getResultList().stream().map(o -> processProperty((Object[]) o)).collect(Collectors.<PropertyVO>toList());
I already have a field that shows agent_id, but not fetched with same field of table Person. I need to retrieve that field agent id alias fetched from left join.
I followed another approach:
Query query = em.createNativeQuery("SELECT" +
" ips.id, ips.agency_id, ips.integrator_property_id, ips.orig_listing_date, ips.contract_type," +
" ips.transaction_type, ips.current_listing_price, ips.current_listing_currency, ips.apartment_number, ips.commercial_residential," +
" ips.commission_percent, ips.commission_value, ips.property_type, ips.street_name, ips.street_number," +
" s.mls_id AS imported," +
" p.INTEGRATOR_SALES_ASSOCIATED_ID AS INTEGRATOR_SALES_ASSOCIATED_ID" +
" FROM test1.ilist_property_summary ips " +
" LEFT JOIN test1.statistics s ON s.mls_id = ips.INTEGRATOR_PROPERTY_ID " +
" LEFT JOIN test1.person p ON p.INTEGRATOR_SALES_ASSOCIATED_ID = ips.INTEGRATOR_SALES_ASSOCIATED_ID " +
"WHERE ips.AGENCY_ID = :agencyId AND (s.statistics_type = 1 OR s.statistics_type IS NULL) AND ips.ORIG_LISTING_DATE BETWEEN :startDate AND :endDate ");
Here field
INTEGRATOR_SALES_ASSOCIATED_ID
is taken from table p, and not from ips. I just selected specific fields so this one could be taken from the other table.

Resources