Reputation: 16271
I am working with Spring Data
2.0.6.RELEASE.
I am working about pagination for performance and presentation purposes. Here about performance I am talking about that if we have a lot of records is better show them through pages
I have the following and works fine:
interface PersonaDataJpaCrudRepository extends PagingAndSortingRepository<Persona, String> {
}
The @Controller
works fine with:
@GetMapping(produces=MediaType.TEXT_HTML_VALUE)
public String findAll(Pageable pageable, Model model){
Through Thymeleaf
I am able to apply pagination. Therefore until here the goal has been accomplished.
Note: The Persona
class is annotated with JPA
(@Entity
, Id
, etc)
Now I am concerned about the following: even when pagination works in Spring Data
about the amount the records, what about of the content of each record?.
I mean: let's assume that Persona
class contains 20 fields (consider any entity you want for your app), thus for a view based in html
where a report only uses 4 fields (id, firstname, lastname, date), thus we have 16 unnecessary fields for each entity in memory
I have tried the following:
interface PersonaDataJpaCrudRepository extends PagingAndSortingRepository<Persona, String> {
@Query("SELECT p.id, id.nombre, id.apellido, id.fecha FROM Persona p")
@Override
Page<Persona> findAll(Pageable pageable);
}
If I do a simple print in the @Controller
it fails about the following:
java.lang.ClassCastException:
[Ljava.lang.Object; cannot be cast to com.manuel.jordan.domain.Persona
If I avoid that the view fails with:
Caused by:
org.springframework.expression.spel.SpelEvaluationException:
EL1008E:
Property or field 'id' cannot be found on object of type
'java.lang.Object[]' - maybe not public or not valid?
I have read many posts in SO such as:
I understand the answer and I am agree about the Object[]
return type because I am working with specific set of fields.
Object[]
with the current API of Spring Data
?Upvotes: 0
Views: 3558
Reputation: 209
Have a look at Spring data Projections. For example, interface-based projections may be used to expose certain attributes through specific getter methods.
Interface:
interface PersonaSubset {
long getId();
String getNombre();
String getApellido();
String getFecha();
}
Repository method:
Page<PersonaSubset> findAll(Pageable pageable);
Upvotes: 5
Reputation: 2029
If you only want to read a specific set of columns you don't need to fetch the whole entity. Create a class containing requested columns - for example:
public class PersonBasicData {
private String firstName;
private String lastName;
public PersonBasicData(String firstName, String lastName) {
this.firstName = fistName;
this.lastName = lastName;
}
// getters and setters if needed
}
Then you can specify query using @Query
annotation on repository method using constructor expression like this:
@Query("SELECT NEW some.package.PersonBasicData(p.firstName, p.lastName) FROM Person AS p")
You could also use Criteria API to get it done programatically:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<PersonBasicData> query = cb.createQuery(PersonBasicData.class);
Root<Person> person = query.from(Person.class);
query.multiselect(person.get("firstName"), person.get("lastName"));
List<PersonBasicData> results = entityManager.createQuery(query).getResultList();
Be aware that instance of PersonBasicData
being created just for read purposes - you won't be able to make changes to it and persist those back in your database as the class is not marked as entity and thus your JPA provider will not work with it.
Upvotes: 3