hibernateの次のJAVAモデルを考えてみます。
@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;
}
私が欲しいのは:
- 個人にフィルタリングを適用する(静的に定義)
- 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で可能ですか?何を使うの?基準?Querydsl?ストリーム?(必ずしもJavaサンプルに固執しないでください)
stream()
して、データベースのクエリに使用できることがわかります。これは私の質問に部分的に答えることができると思います。しかし、誰かが具体的な例で答えることができるかどうか(できればormとしてhibernateを使用するかどうか)を確認するために、開いたままにします。
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());
どこPredicate
で使用filter
した後map
のpingは基づいているPersonV0