spring data jpa with native query - spring

I am trying spring data JPA. My repository method is like this:
#Query(value = "SELECT * FROM test_result WHERE FK_TEST_PAPER_ID=?1 AND PERCENTAGE_OBTAINED BETWEEN :?2 AND :?3 ?#{#pageable}", nativeQuery = true)
Page<TestResult> findResult(long testPaperId, Float minpercentage, Float maxpercentage, Pageable pageInfo);
My service implementation code is like this:
Page<TestResult> getAllResult1 = testResultRepository.findResult(testPaperId,minpercentage,maxpercentage,pageInfo);
And I am getting this error : Paging query needs to have a Pageable parameter!
I am new to spring. Please help.

Remove ?#{#pageable} from query

Related

How to get Distinct record from JPA

I have implemented a method which gives me specification, but what I want is the query should be as below:
Select Distinct *
From (another select query)
I generate query dynamically.
How do I perform the same using specification in Spring Boot?
Try something like this
Specification<T> spec = getSpecification();
Specification<T> distinctSpec = (root, query, cb) -> {
query.distinct(true);
return spec.toPredicate(root, query, cb);
};
if you want to get distinct records, you have to write a query like this in the repository.
The below query gives the distinct author from the post table.
#Query("select distinct author from Post")
List<String> findUniqueAuthor();
Write this in the repository
#Query(value = "Select Distinct * From (another select query)", nativeQuery = true)
List<Object> findUniqueData();

SPring Data JPA nativeQuery #Query with DTO -No converter found capable of converting

I have to use multiple tables,so i have used NativeQuery along with #Query annotation
#Query( value= "select c.logo logo ,c.name customerName,(sum(wp.completion_percent)) completionPercent,sum(ks.days) days ,count(u.id) fteCount,count(w.wp_order_id) wpCount FROM wp_order w, Project p , Assignee a , User u ,Customer c ,Domains d,kpi_status ks ,wp_kpi wp where w.project_id=p.id and p.id=a.project_id and p.cust_id=c.id and w.id=wp.wpo_id and wp.id=ks.wp_kpi_id and a.status=?1"
,nativeQuery=true)
public List<WPOrder> getProjectJoin(String status);

Annotation argument error while using $slice in Spring MongoDB Repository with #Query in Kotlin

I am using Spring Boot Kotlin with MongoDB. In this project, I have the one class which has an array attribute named pointsEntry. I have been trying to use the operator $slice to get only the first pointsEntry of all list when retrieving them in my own findAll method. This query works when tried in my Mongo client:
db.getCollection('collectionName').find( {}, { "pointsEntry" : { $slice: 1 } } )
However, I tried a similar approach in my Spring Boot project with the #Query annotation and it always gives error
An annotation argument must be a compile-time constant
#Query(value = "{}",fields = "{pointsEntry: {'$slice' : ?0}}")
fun findAll() : List<DocumentName>
It is missing ' single quote on pointsEntry field
#Query(value = "{}", fields = "{'pointsEntry': {'$slice' : ?0}}")
You need to escape the $ sign
#Query(value = "{}",fields = "{pointsEntry: {\$slice : ?0}}")

Spring data querying with complex object marked by #Param

I have an entity with aggregation information that I am going to receive from database:
class BookStats {
String author
String title
Integer count
}
My question is could I use some complex object in Repository to filter statistic information. Something like that:
#Query(value = "SELECT new com.test.book.BookStats(b.author, b.title, count(b)) from Book b where b.title = :filter.title and b.author= :filter.author")
List<BookStats> calculateBookStats (#Param("filter") Filter filter)
Spring Data JPA allows to use SpEL :
#Query(value = "SELECT new com.test.book.BookStats(b.author, b.title, count(b)) from Book b where b.title = :#{#filter.title} and b.author= :#{#filter.author}")
List<BookStats> calculateBookStats (#Param("filter") Filter filter)
More info here.

JPA #OneToMany by default is not so Lazy and fetch everything

Current project runs on Spring + Openjpa + Roo. I have an entity like this
public class Zoo{
....
#OneToMany(mappedBy="zoo", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private List<Elephant> elephants;
#OneToMany(mappedBy="zoo", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private List<Jaguar> jaguars;
#OneToMany(mappedBy="zoo", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private List<Tiger> tigers;
....
}
Then I have a simple UI page just trying to update the Zoo name, however from SQL trace log after the simple query
SELECT t0.id, t0.name
FROM Zoo t0
WHERE t0.id = ?
there are a query like this
SELECT * FROM Zoo, Tiger, TigerProduct, TigerFood, FoodSupplier, SupplierContacts...
and a hundreds queries like this:
SELECT * FROM TigerProduct where tiger.id =: id_1
.....
SELECT * FROM TigerProduct where tiger.id =: id_n
....
....
SELECT * FROM TigerFood where tiger.id =: id_1
....
SELECT * FROM TigerFood where tiger.id =: id_n
And same to Jaguar and Elephant as well. This makes this simple action really slow when there is large amount of data resides in the database.
The java code for the first query and the ones after is pretty simple:
public static Zoo findZoo(Long id) {
if (id == null) return null;
return entityManager().find(Zoo.class, id);
}
from above it looks like the default FetchType.Lazy on #OneToMany relation is not so lazy at all that JPA tries to pull all data on the chain.
So what's going on and how to clear this situation? I only prefer to have the first query and that's it
FetchType.Lazy is only a hint, and not a requirement, as the documentation says. So you cannot rely on this behavior, you can only hope that your JPA provider respects your hint. Also JPA does not forces a way how the JPQL queries or entitymanager calls are converted to SQL code, so it is somehow our duty to select a JPA provider+version that knows how to do things better (as we define what better means). This was probably a decision that should encourage the competition between JPA providers.

Resources