Witam,
Przepraszam za zamieszanie w tamtym poście stwierdziłem, że napiszę wszystko od nowa z racji tego, że nie do końca rozumiem waszego przesłania. W większej części dlatego, że dopiero się uczę, a mniejszej, że nie do końca chyba się zrozumieliśmy.
Na wstępie wkleję kod, który jest wykorzystywany:
Encja:
public class UserDetail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String city;
private int age;
public UserDetailDto toUserDetailDto() {
return new UserDetailDto(
this.city,
this.age);
}
@Data
@AllArgsConstructor
public static class UserDetailDto {
private String city;
private int age;
}
}
public abstract class GetQueryAbstractService<B, R> {
@PersistenceContext
protected EntityManager entityManager;
protected abstract Class<B> getClazz();
protected abstract Predicate getPredicate(Predicate predicate, CriteriaBuilder builder, Root r, List<SearchCriteria> params);
protected abstract List<R> getDtos(CriteriaQuery<B> query);
public List<R> execute(String search) {
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
final CriteriaQuery<B> query = builder.createQuery(getClazz());
final Root r = query.from(getClazz());
List<SearchCriteria> params = new ArrayList<>();
if (search != null) {
Pattern pattern = Pattern.compile("(\\w+?)(:|<|>)(\\w+?),");
Matcher matcher = pattern.matcher(search + ",");
while (matcher.find()) {
params.add(new SearchCriteria(matcher.group(1), matcher.group(2), matcher.group(3)));
}
}
Predicate predicate = builder.conjunction();
predicate = getPredicate(predicate, builder, r, params);
query.where(predicate);
return getDtos(query);
}
}
@Service
public class GetQueryUserDetailService extends GetQueryAbstractService<UserDetail, UserDetail.UserDetailDto> {
@Override
protected Class<UserDetail> getClazz() {
return UserDetail.class;
}
@Override
protected Predicate getPredicate(Predicate predicate, CriteriaBuilder builder, Root r, List<SearchCriteria> params) {
UserSearchQueryCriteriaConsumer searchConsumer = new UserSearchQueryCriteriaConsumer(predicate, builder, r);
params.forEach(searchConsumer);
return searchConsumer.getPredicate();
}
@Override
protected List<UserDetail.UserDetailDto> getDtos(CriteriaQuery<UserDetail> query) {
return entityManager
.createQuery(query)
.getResultStream()
.map(UserDetail::toUserDetailDto)
.collect(Collectors.toList());
}
}
Teraz przedstawię, co chcę osiągnąć:
Mam kilka różnych encji z różnymi wartościami i chcę zbudować funkcję odpowiedzialną, która będzie odpowiedzialna za wyszukiwanie danych. np: ?search=city:Gdynia
I tutaj się pojawia temat, jak w takim razie powinno to się zrealizować, bo pojawiły się głosy, że mam to już źle zrealizowane na etapie projektowania(choć osobiście na tym etapie wolałbym to jednak zostawić w ten sposób, niż zmieniać wszystko)
Z czym mam problem ?
Aktualnie klasa GetQueryUserDetailService przyjmuje UserDetail, UserDetail.UserDetailDto
Natomiast jeśli chciałbym użyć powyższej funkcjonalności dla innych klas, to musiałbym to przerobić na klasę generyczną, w innym przypadku dla każdej encji musiałbym tworzyć po prostu nową klasę.
Przepraszam za tamto zamieszanie, a za pomoc z góry dziękuje.