Considere o seguinte modelo JAVA para o hibernate :
@Entity
@Table
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long id;
@Column
public String firstName;
@Column
public String lastName;
@Column
public Boolean active;
}
e o seguinte modelo para serialização da API (usando o controlador de descanso de inicialização por mola ):
public class PersonVO {
public Long id;
public String fullName;
}
O que eu quero é:
- Aplique alguma filtragem na Pessoa (definida estaticamente)
- Aplique alguma filtragem no PersonVO (obtenha @RequestParam)
Em C # .NET eu poderia fazer como:
IQueryable<Person> personsQuery = entityFrameworkDbContext.Persons;
// FIRST POINT - Here i could make some predefined filtering like 'only active', 'from the same city'... at the database model
personsQueryWithPreDefinedFilters = personsQuery.Where(person => person.active == true);
IQueryable<PersonVO> personsProjectedToVO = personsQueryWithPreDefinedFilters.Select(person => new PersonVO()
{
id = person.id,
fullName = person.firstName + " " + person.lastName
});
// SECOND POINT - At this point i could add more filtering based at PersonVO model
if (!String.IsNullOrWhiteSpace(fullNameRequestParameter)) {
personsProjectedToVO = personsProjectedToVO.Where(personVO => personVO.FullName == fullNameRequestParameter);
}
// The generated SQL at database is with both where (before and after projection)
List<PersonVO> personsToReturn = personsProjectedToVO.ToList();
O que eu recebi em Java é:
CriteriaBuilder cb = this.entityManager.getCriteriaBuilder();
CriteriaQuery<PersonVO> cq = cb.createQuery(PersonVO.class);
Root<Person> root = cq.from(Person.class);
// FIRST POINT - Here i could make some predefined filtering like 'only active', 'from the same city'... at the database model
cq.where(cb.equal(root.get(Person_.active), true));
Expression<String> fullName = cb.concat(root.get(Person_.firstName), root.get(Person_.lastName));
cq.select(cb.construct(
PersonVO.class,
root.get(Person_.id),
fullName
));
// SECOND POINT - At this point i could add more filtering based at PersonVO model??? HOW???
if (fullNameRequestParameter != null) {
cq.where(cb.equal(fullName, fullNameRequestParameter));
// i only could use based at the fullName expression used, but could i make a Predicate based only on PersonVO model without knowing or having the expression?
}
Eu quero ter separado a "projeção para o modelo VO" da "expressão onde" aplicada a ele, mas aplicada indiretamente se usada uma coluna projetada (como fullName).
Isso é possível em Java? Usando o que? Critério? Querydsl? Corrente? (não adira necessariamente à amostra do java)
stream()
para consultar o banco de dados. Eu acho que isso pode responder parcialmente à minha pergunta. Mas vou mantê-lo aberto para ver se alguém pode responder isso com um exemplo concreto (de preferência usando o hibernate como orm).
Stream
s, você poderia ter feito algo como -personList.stream().filter(p -> p.active).map(p -> new PersonV0(p.id, p.firstName + " " + p.lastName)).filter(pv -> pv.fullName.equals(fullNameRequestParameter)).collect(Collectors.toList());
onde oPredicate
usado no pingfilter
posteriormap
se baseiaPersonV0