Chociaż moje pytanie dotyczy generycznych Java, umieściłem trochę kodu związanego z JPA, aby pokazać rzeczywisty kontekst.Generics Java: jak uzyskać ogólny typ z metody?
Pracuję z zapytaniami opartymi na JPA 2.0 i API opartym na kryteriach. Wszystkie moje zapytania mają ten sam wzorzec (porównywanie prostych atrybutów, brak nawigacji po ścieżce), więc staram się napisać ogólną klasę, aby poradzić sobie z WZP, zachowując logikę biznesową w oddzielnych klasach. Moim celem jest posiadanie metody, która, biorąc pod uwagę typ jednostki i mapę, która przechowuje pary (nazwa pola -> pożądana wartość) definiująca kryteria, zwraca komponent bean (lub zbiór fasoli) z wartością niektórych pól encji .
Wszystkie moje podmioty implementują interfejs Persistible
, a wszystkie moje obiekty przenoszenia dziedziczą po QueryBean
. Uważam, że te klasy nie są związane z problemem, więc pomijam ich kod.
Poniższy kod jest urywek mojego pierwszego podejścia (należy zakładać cb jest prawidłowym wystąpienie CriteriaBuilder):
protected <T extends QueryBean, TT extends Persistible> Collection<T> executeQueryEntity
(Class<T> type, Class<TT> rootType, QueryConfig queryConfig, Map<String, Object> parameters) {
// (...) Initialization goes here
CriteriaQuery<T> c = cb.createQuery(type);
// FROM CLAUSE
Root<TT> root = c.from(rootType);
// SELECT CLAUSE
List<String> constructorParams = queryConfig.getTargetAttributes();
Selection<?>[] selectArray = new Selection<?>[constructorParams.size()];
for (int i = 0; i < constructorParams.size(); i++) {
selectArray[i] = root.get(constructorParams.get(i));
}
c.select(cb.construct(type, selectArray));
// WHERE CLAUSE
for (String filter : parameters.keySet()) {
if (queryConfig.getFieldConfiguration().get(filter).compareUsingEquals()) {
// SOME PREDICATE
}
else {
// SOME OTHER PREDICATE
}
}
// (...) Rest of the code goes here
}
Mój interfejs QueryConfig jest następujący:
public interface QueryConfig {
List<String> getTargetAttributes();
Map<String, FieldConfiguration> getFieldConfiguration();
}
Ponieważ jestem używające już klasy QueryConfig
, która dostarcza informacji o zapytaniu (takich jak parametry potrzebne dla konstruktora QueryBean lub informacji o polach encji), pomyślałem, że byłoby miło pobrać typ jednostki z tej klasy, zamiast przekazywać ją jako Cla parametr ss. Wnioskuję z this mowa, że nie można zrobić bezpośrednio, więc próbowałem następujące rozwiązania:
Dodawanie metodę QueryConfig tak:
Class< ? extends Persistible> getTargetEntity();
Dodawanie metodę pośrednią tak:
public <T extends QueryBean> Collection<T> queryMany(Class<T> type, QueryConfig config, Map<String, Object> parameters) {
executeQueryEntity(type, config.getTargetEntity(), parameters);
}
Ale nie będzie się kompilować. Uważam, że powody są tutaj wyjaśnione: Type mismatch for Class Generics, ale właściwie nie rozumiem odpowiedzi. Moje pytania: czy istnieje sposób na uniknięcie podania parametru Class< TT >
do metody execute? Czy jest to dobry sposób na rozwiązanie problemu, czy też powinienem to zmienić? Wszelkie poprawki do kodu są również mile widziane!
swój angielski, nawiasem mówiąc, jest rzeczywiście bardzo dobre. Nawet tego nie zauważyłem, dopóki tego nie wskazałeś. – Zyerah
@Telthien Dziękuję, zrobiłem to najlepiej, jak mogłem =) – DiegoAlfonso
Twoja najlepsza przechodzi lepiej niż wielu native speakerów! Wysiłek jest naprawdę doceniany. – Zyerah