2013-04-24 4 views
7

제 생각에는 Java generics에 관한 것이지만 실제 컨텍스트를 표시하기 위해 JPA 관련 코드를 넣었습니다.Java generics : 메소드에서 제네릭 형식을 얻는 방법?

JPA 2.0 및 Criteria API 기반 쿼리로 작업하고 있습니다. 모든 쿼리는 동일한 패턴 (간단한 속성 비교, 경로 탐색 필요 없음)을 따르므로 비즈니스 로직을 분리 된 클래스로 유지하면서 JPA를 처리하기위한 일반 클래스를 작성하려고합니다. 내 목표는 엔티티 유형 및 조건을 정의하는 쌍 (필드 이름 -> 원하는 값)을 저장하는 맵이 주어진 경우 엔 엔티티 필드의 값 중 일부가 포함 된 bean (또는 beans 컬렉션)을 리턴하는 메소드를 갖는 것입니다 .

내 모든 개체가 에서 상속되는 동안 모든 내 개체는 Persistible 인터페이스를 구현합니다. 문제와 관련이없는 클래스를 고려하므로 코드를 건너 뜁니다.

다음 코드는 (CB 유효한 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 
} 

내 QueryConfig 인터페이스는 다음과 같습니다

public interface QueryConfig { 

List<String> getTargetAttributes(); 
Map<String, FieldConfiguration> getFieldConfiguration(); 

} 

난 이후 쿼리의 정보를 제공하는 QueryConfig 클래스를 이미 사용하고있는 경우 (QueryBean 생성자에 필요한 매개 변수 나 엔터티 필드에 대한 정보 등), Cla로 전달하는 대신 해당 클래스의 엔터티 형식을 가져 오는 것이 좋을 것이라고 생각했습니다. ss 매개 변수. 나는 직접 수행 할 수 없음을 this 질문에서 추론, 그래서 나는 다음과 같은 해결 방법을 시도했다 :이 같은 중간 방법을 추가

Class< ? extends Persistible> getTargetEntity(); 

:이 같은 QueryConfig하는

방법을 추가를

public <T extends QueryBean> Collection<T> queryMany(Class<T> type, QueryConfig config, Map<String, Object> parameters) { 
    executeQueryEntity(type, config.getTargetEntity(), parameters); 
} 

하지만 컴파일되지 않습니다. 이유는 여기에 설명되어 있다고 생각합니다 : Type mismatch for Class Generics하지만 실제로 대답을 이해하지 못했습니다. 내 질문은 : Class< TT > 매개 변수를 실행 메서드에 전달하지 않는 방법이 있습니까? 문제를 해결하는 좋은 방법인가요? 아니면 모든 것을 리팩터링해야합니까? 코드 개선 사항도 환영합니다!

+1

는 영어, 그런데, 실제로 매우 좋은 당신 : 당신이 할 수있는

한 가지 방법은 같은 수 있습니다

public interface QueryConfig <T extends Persistable> { Class<T> getTargetEntity(); List<String> getTargetAttributes(); Map<String, FieldConfiguration> getFieldConfiguration(); } 

QueryConfig

하고 queryMany 방법의 유형 정보를 제공하고 있습니다. 나는 당신이 그것을 지적하기 전까지는 실제로주의를 기울이지 않았다. – Zyerah

+2

@ 텔 티엔 고맙습니다, 최선을 다했습니다. =) – DiegoAlfonso

+1

당신의 최고는 많은 원어민 강사들보다 더 잘 전달됩니다! 노력은 진심으로 감사드립니다. – Zyerah

답변

2

내가 할 확실히 당신이 당신의 접근 방식은 작동합니다 생각하는 이유하지 : Class< ? extends Persistible> getTargetEntity();QueryConfig가 컴파일러에 의해 참조 될 수있는 유형의 정보를 제공하지 않으며, 당신이 생각하는 왜 컴파일러는 당신이 유형을 "추측"할 수 있습니다 돌아올거야, 너를 위해 타입 검사를 할거야?

public <T extends QueryBean, TT extends Persistible> 
Collection<T> queryMany(Class<T> type, 
         QueryConfig<TT> config, 
         Map<String, Object> parameters) { 
    executeQueryEntity(type, config.getTargetEntity(), parameters); 
} 
+0

대단히 감사합니다 !!비슷한 것을 시도했지만 queryMany의 서명에 QueryConfig의 형식 매개 변수가 없어서 컴파일러가 클래스에서 클래스 으로의 변환에 대해 불평했습니다. – DiegoAlfonso

관련 문제