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.