Spring data pagination with entity graph - spring-data-jpa

I need to use pagination in conjuntion with a custom query using an Entity Graph. My repository looks like this:
#Repository
public interface MaintenanceRepository extends JpaRepository<Maintenance, Long>, QueryDslPredicateExecutor<Maintenance> {
#EntityGraph(value = "Maintenance.Graph")
#Query("select m from Maintenance m where m.detail.type.company = ?1 ")
Page<Maintenance> findWithCompany(Company company, Pageable pageable);
}
For comparison, I am getting the Maintenances using this method and using findAll method inherited from QueryDslPredicateExecutor:
...
Pageable pageable = new PageRequest(pageNumber, pageSize, Sort.Direction.DESC, "creationTime");
Page<Maintenance> page = repo.findWithCompany(company, pageable);
Page<Maintenance> page2 = repo.findAll(QMaintenance.maintenance.detail.type.company.eq(company), pageable);
LOGGER.debug("Old: {} - {}, New: {} - {}", page.getTotalElements(), page.getContent().size(), page2.getTotalElements(), page2.getContent().size());
...
In the data base there is 3 register of Maintenances and when I call this method using a page with 1, 2 and 50 page size, I get this log.
[28/03/2017 14:14:36] [DEBUG] Old: 3 - 1, New: 3 - 1 //total - content
[28/03/2017 14:15:09] [DEBUG] Old: 3 - 2, New: 3 - 2
[28/03/2017 14:15:27] [DEBUG] Old: 3 - 3, New: 3 - 3
According to the logs the pagination is working fine but the querys are very different when I use my repository method and the inherited findAll method.
//Query for my repository method
Hibernate: select ... where maintenanc0_.detalle=detail1_.id and detail1_.tipo=type2_.id and type2_.compania=? order by maintenanc0_.fecha desc
//Query for inherited `findAll` method
Hibernate: select ... where maintenanc0_.detalle=detail1_.id and detail1_.tipo=type2_.id and type2_.compania=? order by maintenanc0_.fecha desc limit ?
Two logs have been cut for show relevant information, and in the second query the entity graph hints has not been used because I can not provide it with a Predicate object, but I understand and that is not my problem.
Having this results, I understand that with my repository method (first query) I am not getting a real pagination because spring is filling the list with the correct content size, and the query doesn't have limit keyword.
With the second query, I'm getting a real pagination because the data base is doing the work.
According to Spring Data reference I should be able to do pagination with custom query method.
My concern is the performance, because I don't want to have much data loaded in memory and I need get real pagination done at data base level.
Using QueryDslPredicateExecutor is fine but I can't set a hint for entity graph.

Related

JPA Specification Select returns all columns instead of specific

I am using JPA Specification , need to select specific columns only.
This is the code:
Specification<Item> spec = (root, query, builder) -> {
query.select(root.get("Id"));
Predicate predicate = builder.equal(root.get("Id"), "12345");
return predicate;
};
In log I see that all columns from Item Entity are selected from database.
Is it a bug?
 usage:
interface:
public interface Repo extends PagingAndSortingRepository<Item,String>, JpaSpecificationExecutor<Item> {
}
call:
repo.findAll(spec );
JpaSpecificationExecutor is specifically defined to return the entity type. I suspect it is ignoring the .select(root.get("Id")).
Normally you would use Specifications if you have an extremely dynamic set of conditions you are querying by. If you have just a few parameters you need to search by, I would use a derived query, or a named query.
public interface Repo extends PagingAndSortingRepository<Item,String>, JpaSpecificationExecutor<Item> {
#Query("Select i.id from Item i where name=:name")
Long getIdforName(String name);
}

Issue displaying count results in WebApi call

I have a stored procedure that return a record count in SQL based on certain criteria. I am trying to retrieve this count in EF Core 3 so I can pass it into an angular app. When I test the SP in SQL it returns the expected result. In the controller I configured an action route to call the SP
[Route ("[action]")]
public async Task<IActionResult> GetCountOverdueLowPriorityWorkOrders()
{
var GetCountOverdueLowPriorityWorkOrders = await _repo.GetCountOverdueLowPriorityWorkOrders();
return Ok(GetCountOverdueLowPriorityWorkOrders);
}
When I test this call from Postman, I get the following error:
System.InvalidOperationException: The required column 'ID' was not present in the results of a 'FromSql' operation.
I am fairly new to programming, so any help would be greatly appreciated.
Thanks!
The column containing the values for COUNT(id) needs to be aliased as id.
Try this
SELECT COUNT(id) as ID FROM Workorders WHERE Severity = 1 AND Due < CAST(Current_TimeStamp AS DATE)

Spring Data: how works Pageable together with #Query? (Interface Projection)

I am working with Spring Data for the 2.0.6.RELEASE version
I am confused about the following about pagination and projection
The domain class is named Persona working with lombok and annotated with JPA (#Entity etc ..)
I have the following about projection:
public interface PersonaProjection {
String getId();
String getNombre();
String getApellido();
Date getFecha();
}
About the repository I have the following:
interface PersonaDataJpaCrudRepository extends PagingAndSortingRepository<Persona, String> {
Page<PersonaProjection> findAllProjectedBy(Pageable pageable);
}
Until here all work fine.
The #Controller has this body:
#GetMapping(path="/complete", produces=MediaType.TEXT_HTML_VALUE)
public String findAllComplete(Pageable pageable, Model model){
logger.info("findAllComplete ...");
Page<PersonaProjection> personasPage = personaService.findAll(pageable);
model.addAttribute("personasPage", personasPage);
return "persona/findAllComplete";
}
The view is based with Thymeleaf and shows the data how is expected
Practically from three days ago I was working with the following:
#Query("SELECT p.id, p.nombre, p.apellido, p.fecha FROM Persona p")
Page<PersonaProjection> findAllProjectedBy(Pageable pageable);
Observe it has a #Query just to visual purposes. It to help to understand quickly what fields are retrieved.
And worked fine, but just until today without any variation practically the view for that fields remains in blank, none exception thrown, through the console through some special variations of the #Controller method I can confirm:
Page request [number: 0, size 10, sort: UNSORTED]
PageNumber: 0, PageSize: 10, Offset: 0
Page 1 of 11 containing com.sun.proxy.$Proxy84 instances
Number: 0, NumberOfElements: 10
Size: 10, TotalElements: 107, TotalPages: 11
PageNumber: 0, PageSize: 10, Offset: 0
The output shown above in the previous three days appears with and without the Query addition.
After to do a research I found the following example for this class:
CustomerRepository.java
Where it has the following method:
/**
* Projection interfaces can be used with manually declared queries, too. Make sure you alias the projects matching
* the projection fields.
*
* #return
*/
#Query("select c.firstname as firstname, c.lastname as lastname from Customer c")
Collection<CustomerProjection> findsByProjectedColumns();
Observe this note:
Make sure you alias the projects matching the projection fields.
Thus if I use:
#Query("SELECT p.id as id, p.nombre as nombre, p.apellido as apellido, p.fecha as fecha FROM Persona p")
Page<PersonaProjection> findAllProjectedBy(Pageable pageable);
Works but observe is redundant, it about that the alias is the same than the field name.
Thus following questions:
Why the first #Query version works some days ago and now no?. Here my big confusion. (I am assuming that com.sun.proxy.$Proxy84 instances is involved)
Why is mandatory use this alias as within the #Query? It is not documented in the 4.3.11. Projections section, even more there is no sample showing an interface projection working together with a #Query

Having conditional multiple filters in Morphia query for Mongo database

Environment : MongoDb 3.2, Morphia 1.1.0
So lets say i am having a collection of Employees and Employee entity has several fields. I need to do something like apply multiple filters (conditional) and return a batch of 10 records per request.
pesudocode as below.
#Entity("Employee")
Employee{
String firstname,
String lastName,
int salary,
int deptCode,
String nationality
}
and in my EmployeeFilterRequesti carry the request parameter to the dao
EmployeeFilterRequest{
int salaryLessThen
int deptCode,
String nationality..
}
Pseudoclass
class EmployeeDao{
public List<Employee> returnList;
public getFilteredResponse(EmployeeFilterRequest request){
DataStore ds = getTheDatastore();
Query<Employee> query = ds.createQuery(Emploee.class).disableValidation();
//conditional request #1
if(request.filterBySalary){
query.filter("salary >", request.salary);
}
//conditional request #2
if(request.filterBydeptCode){
query.filter("deptCode ==", request.deptCode);
}
//conditional request #3
if(request.filterByNationality){
query.filter("nationality ==", request.nationality);
}
returnList = query.batchSize(10).asList();
/******* **THIS IS RETURNING ME ALL THE RECORDS IN THE COLLECTION, EXPECTED ONLY 10** *****/
}
}
SO as explained above in the code.. i want to perform conditional filtering on multiple fields. and even if batchSize is present as 10, i am getting complete records in the collection.
how to resolve this ???
Regards
Punith
Blakes is right. You want to use limit() rather than batchSize(). The batch size only affects how many documents each trip to the server comes back with. This can be useful when pulling over a lot of really large documents but it doesn't affect the total number of documents fetched by the query.
As a side note, you should be careful using asList() as it will create objects out of every document returned by the query and could exhaust your VM's heap. Using fetch() will let you incrementally hydrate documents as you need each one. You might actually need them all as a List and with a size of 10 this is probably fine. It's just something to keep in mind as you work with other queries.

Linq query to get results from DB in ASP.NET MVC 2

How do I query using Ling to Entities.
I want to get back the total number of rows for a specific user.
I created a table with an ID(PK), Username, and PhoneNumber.
In my controller, I am able to do this and see my entities:
public ActionResult UserInfo()
{
using (UserInfoEntities db = new UserInfoEntities())
{
}
return View();
}
How do I query to return the total number of rows and declare it to a variable (totalrows) so that I can do thge following:
ViewData["TotalRows"] = totalrows
If there is a better way I am open to suggestions...
Thanks!!
Probably something like:
int count = db.SomeTable.Where(r => r.Username.Equals("username")).Count();
Yep Matthew is right. The count method does exactly what you need! Although, I would recommend looking at ViewModels to pass your data to your view (rather than ViewData) and some kind of DAL pattern, such as the repository pattern, for querying your entities.