考虑以下JAVA模型,用于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;
}
而下面是API序列化的模型(使用 Spring Boot Rest Controller):
public class PersonVO {
public Long id;
public String fullName;
}
我希望实现以下功能:
- 对于 Person(静态定义),应用一些过滤
- 对于 PersonVO(由 @RequestParam 获取),应用一些过滤
在 C# .NET 中,我可以这样做:
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();
我掌握的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?
}
我希望将“投影到VO模型”的操作与应用于它的“where表达式”分离,但如果使用了像fullName这样的投影列,则间接应用它。
这在Java中可行吗?使用什么工具?Criteria?Querydsl?Stream?(不一定局限于Java示例)
Stream
,您可以像这样做 -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());
在map
之后使用的Predicate
基于PersonV0
。 - Namanstream()
来查询数据库。我认为这可以部分回答我的问题。但我会保持开放状态,看看是否有人能用具体的例子来回答(最好使用 hibernate 作为 ORM)。 - jvitor83