Betrachten Sie das folgende JAVA-Modell für den Ruhezustand :
@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;
}
und das folgende Modell für die API-Serialisierung (unter Verwendung des Spring Boot Rest Controllers):
public class PersonVO {
public Long id;
public String fullName;
}
Was ich will ist:
- Lassen Sie die Person filtern (statisch definiert)
- Lassen Sie einige Filter bei der PersonVO anwenden (erhalten Sie von @RequestParam)
In C # .NET könnte ich wie folgt machen:
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();
Was ich in Java bekommen habe ist:
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?
}
Ich möchte die "Projektion auf das VO-Modell" von dem darauf angewendeten "where-Ausdruck" getrennt haben, habe sie aber indirekt angewendet, wenn eine projizierte Spalte (wie fullName) verwendet wird.
Ist das in Java möglich? Mit was? Kriterien? Querydsl? Strom? (Halten Sie sich nicht unbedingt an die Java-Probe)
stream()
Abfragen der Datenbank ermöglichen kann. Ich denke, das kann meine Frage teilweise beantworten. Aber ich werde es offen halten, um zu sehen, ob jemand dies mit einem konkreten Beispiel beantworten kann (vorzugsweise mit Ruhezustand als Orm).
Stream
s hätten Sie so etwas wie -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());
wo derPredicate
imfilter
After-map
Ping verwendete basiertPersonV0