#Query with 2 parameters in Java Spring - java

I'm looking for a solution for following problem -
i want to create a #Query like this:
#Query("select s from Student s where s.name like %?1% and s.surname like %?1%")
because I need to be able to show student with given name and surname. I was able to make it sort of work, because when I change and with or, the query shows entries with either given name or given surname, but as soon as i change it back to and nothing shows.
interface StudentRepository extends JpaRepository<Student, Integer> {
#Query("select s from Student s where s.name like %?1% and s.surname like %?1%")
Page<Student> findByNameAndSurname( String name, String surname, Pageable pageable);
}
#GetMapping
Page<Student> getAllStudents(#RequestParam Optional<String> name,
#RequestParam Optional<String> surname,
#RequestParam Optional<Integer> page,
#RequestParam Optional<String> sortBy) {
return repository.findByNameAndSurname(name.orElse("_"),
surname.orElse("_"),
PageRequest.of(
page.orElse(0), 5,
Sort.Direction.ASC, sortBy.orElse("id")));
I also have second question, is it possible to remove this code that shows at the end of JSONs while using pageRequest - I would like only the Student entries to show without this if possible
{"content":[],"pageable":{"sort":{"empty":false,"sorted":true,"unsorted":false},"offset":0,"pageNumber":0,"pageSize":5,"unpaged":false,"paged":true},"last":true,"totalPages":0,"totalElements":0,"size":5,"number":0,"sort":{"empty":false,"sorted":true,"unsorted":false},"first":true,"numberOfElements":0,"empty":true}
I tried using native query in #Query annotation, I also tried modifying the query itself, using some concat tricks i found online, but nothing works;(

JpaRepository supports the query method so if you want to search the items which contains the place holder values you can do it by just defining the method like below.
Page<Student> findByStartingWithFirstNameAndStartingWithSurname();

?1 is for the first parameter name so you must replace your second ?1 with ?2 to use the parameter surname.
For your second question, you can map your page into a list:
repository.findByNameAndSurname(name.orElse("_"),
surname.orElse("_"),
PageRequest.of(
page.orElse(0), 5,
Sort.Direction.ASC, sortBy.orElse("id"))).stream().toList();

Take a look at your query:
#Query("select s from Student s where s.name like %?1% and s.surname like %?1%")
You have defined two placeholders with ?1 what will result in both placeholders to have the same value. So you're literally searching for someone with the same first and last name, that's why an OR would work here.
I am not familiar with Spring, but reading the following tutorial tells me that you can write your query as follows:
#Query("select s from Student s where s.name like %:firstname% and s.surname like %:lastname%")
You need to bind the parameters with the #Param(var) annotation in your method's parameter list though.
For your last question: You probably shouldn't be returning a Page<Student> from your REST (?) service, but rather a List<Student>.

Related

How to Give dynamic column name to #Query

Here is the method in my repository Interface.
#Query("select ?1 ,count(re) from Tabre group by ?1")
Page<RequestEntity> getGroupByColumnName(String columnName, Pageable pageable);
I would like to give column name dynamically to the query as mentioned above. But I see below error
error :
"I see Parameters are only supported in SELECT clauses when used as
part of a INSERT INTO DML statement".
I tried with single quotes, #{#columnName} with no luck.
Can someone help me on how to give the column name dynamically to the #query

use top with list of parameters

I have this spring data repository method
public FileActivity findTopByFileIDOrderByCreatedDesc(String fileID);
This works fine . But how do I make it work for list of parameters ?
This doesn't work (I can have many FileActivity for file id - but I want only the last one) :
public List<FileActivity> findTopByFileIDOrderByCreatedDesc(List<String> fileIDs);
Spring Data's support for derived queries is useful but for anything other than simple queries it is probably easier and clearer just to define your own JPQL query.
#Query("select f from File f where f.id in :fileIds order by f.created desc")
public Page<FileActivity> findTopFilesById(
#Param("fileIDs") List<String> fileIDs, Pageable pageable);
As JPQL does not have a limit keyword you can simply pass in a Page.
List<String> fileIds = //;
Page<File> page = repository.findTopFilesById(fileIds, new PageRequest(0, fileIds.size());
List<File> files = page.getContent();
You could also dynamically specify the sort order in the PageRequest rather than in the JPQL giving a bit more flexibility:
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/PageRequest.html
public FileActivity findTopByFileIDInOrderByCreatedDesc(Collection<String> fileIDs);
See more examples here
Note - if you use 'Top' then you get only one record. To get more than one record you have to add a number to 'Top' for example: 'Top10'.
More info here

Spring Data: limit result for custom query

In my Spring Data repository I (have to) use custom queries using the #Query annotation. I know I can limit the number of results in a named query like that
Iterable<Person> findFirst5OrderByLastName()
or that it is possible to limit the number of results by passing a pageable like that
Iterable<Person> findByLastName(String lastName, Pageable pageable)
But is it possible to achieve the same when using a custom #Query annotation?
TIA
EDIT
as I see my question is a little confusing, some clearification:
What I want is to limit the number of the results I get, when using a custom query, so that I neither
1) need to specify the result-size through a pageable
2) need to use a named query to specify the result-size
In fact I want the limitation of the number of results to be completely transparent when invoking method (hence not passing a Pageable) and to not rely on the naming-scheme of Spring Data (as the meaning/function of the method is best conveyed through a custom name)
You can try this:
#Entity
#Table(name = "persons")
public class Person {
//...
}
#Query(value = "select * from persons limit 50", nativeQuery = true)
List<Person> getFirst50();
Don't forget to check whether your SQL server supports the limit keyword.
Of course you can use #Query to order a result, it is an JPQL query e.g.
#Query("SELECT u FROM User u ORDER BY u.name ASC")
Further sorting can be done be either providing a PageRequest or using Sort directly.
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.sorting
I would suggest to add "By" but without parameter, it would work:
List<Person> findTop100By();
You need to extend PagingAndSortingRepository
and add method
Page<Person> listAllByPage(Pageable pageable)
See the example
Hello you can try this
#Query("...")
List<YourDTO>getData(Pageable pageable)
In your serviceImpl
List<YourDTO> getData(){
int limit=10;
Pageable pageable = PageRequest.of(0, limit);
return this.repo.getData(pageable);
}
You should avoid nativeQuery

How to update an attribute with spring CrudRepository?

How can I create update methods in spring CurdRepository?
Something like:
interface PersonRepository extends CrudRepository<PersonEntity> {
//update ... set age =: age where name =: name
boolean setAgeByName(age, name);
}
If you ask me: do not use such queries. That's because your second level cache gets eradicated and you get some performance problems (your application will be slightly slower).
And by the way the process you want to do is in reality the following:
you load your entity from the database
change the attribute on the loaded object (via a setter method)
you save your entity to the database (this is done automagically when your transaction ends so you do not need to call PartnerRepository.save(entity) explicitly)
If you want to use a query then I suggest you write your query as you mentioned in your question:
#Modifying
#Query("update Person p set p.age = :age where p.name = :name")
int setAgeByName(#Param("age") int age, #Param("name") String name);
And you get back how many entries have been modified.

Spring data mongoRepository Query sort

I was looking to see how I could introduce a sort into a Query annotation in a repository method that I have.
I already saw this code in Google and here, but I could not make it works
#Query("find({state:'ACTIVE'}).sort({created:-1}).limit(1)")
Job findOneActiveOldest();
#Query("{ state:'ACTIVE', $orderby: {created:-1}, $limit:1 }")
Job findOneActiveOldest();
I know that with pagination I can make it, but in some cases I don't need paginate, so I was wondering how to make it with Query annotation.
Any suggestion please?
I don't think it is possible to do it with #Query annotation. If you dont need to paginate you can just make your repository method use Sort parameter:
#Query("{ state:'ACTIVE' }")
Job findOneActive(Sort sort);
and use it:
yourRepository.findOneActive(new Sort(Sort.Direction.DESC, "created"))
Just use sort parameter of #Query annotation. 1 = ASC, -1 = DESC
#Query(
value = ...,
sort = "{'details.requestTime': -1}"
)
if you also want to have pagination then use Pageable as method argument instead of Sort. Try below code:
#Query("{ state:'ACTIVE' }")
Job findOneActive(Pageable pageable);
yourRepository.findOneActive(new PageRequest(0, 1, new Sort(Sort.Direction.DESC,"created")));

Categories

Resources