2013-04-24 24 views
7

Benim sorum Java jeneriklerle ilgili olsa da, size gerçek bağlamı göstermek için JPA ile ilgili bazı kod koydum. Ben JPA 2.0 ve Kriterler API tabanlı sorgu ile çalışıyorumJava jenerikleri: bir yöntemden genel bir tür nasıl edinilir?

. Tüm sorgularım aynı kalıbı takip eder (basit öznitelikler karşılaştırılır, yol navigasyonu gerekmez), bu yüzden iş mantığını ayrı sınıflarda tutarken JPA ile başa çıkmak için genel bir sınıf yazmaya çalışıyorum. Amacım, bir Varlık türü ve ölçütleri tanımlayan çiftleri (alan adı -> istenen değer) saklayan bir Harita verildiğinde, bazı varlık alanlarının değeriyle bir fasulye (veya çekirdek koleksiyonu) döndüren bir yönteme sahip olmaktır. .

Tüm aktarım nesnelerim QueryBean'dan devralınırken, tüm varlıklarım Persistible arabirimini uygular. Problemle ilgili olmayan sınıfları düşünüyorum, bu yüzden kodlarını atlarım.

Aşağıdaki kodu (cb geçerli CriteriaBuilder örneğidir varsayalım lütfen) benim ilk yaklaşımın snippet'idir şu şekildedir:

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 
} 

Benim QueryConfig arayüzüdür:

public interface QueryConfig { 

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

} 

ben olduğum için zaten sorgu hakkında bilgi sağlayan bir QueryConfig sınıfını kullanarak (QueryBean yapıcısı veya varlık alanları hakkında bilgi için gereken parametreler gibi), bir Cla olarak geçirme yerine varlık sınıfını bu sınıftan almak güzel olacağını düşündüm ss parametresi. Ben doğrudan yapılabilir olamayacağını this sorudan anlaması, bu yüzden aşağıdaki geçici çözümü denedim: Böyle bir ara ekleme yöntemi

Class< ? extends Persistible> getTargetEntity(); 

: Böyle QueryConfig için

bir yöntem ekleme

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

Ama derlemek olmaz. Nedenlerin burada açıklandığını düşünüyorum: Type mismatch for Class Generics ama aslında cevabı anlamadım. Sorularım: Class< TT > parametresini yürütme yöntemine geçirmekten kaçınmanın bir yolu var mı? Bu sorunla başa çıkmak için iyi bir yol mu yoksa tüm şeyi yeniden gözden geçirmem mi gerekiyor? Kodda herhangi bir iyileştirme de kabul edilir!

+1

İngilizce, bu arada, aslında çok iyi Sizin: Yapabileceğiniz

bir yolu gibi olabilir

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

QueryConfig

ve queryMany yönteminde tip bilgiler sunmak. Aslında işaret edene kadar farketmedim bile. – Zyerah

+2

@Telthien Teşekkür ederim, ben yapabildiğim en iyisini yaptım =) – DiegoAlfonso

+1

En iyi anadiliniz birçok yerli konuşmacıdan daha iyi geçer! Çaba gerçekten takdir ediliyor. – Zyerah

cevap

2

yapmam oldukça size yaklaşım çalışacağını düşünüyorum nedenini alamadım: Class< ? extends Persistible> getTargetEntity(); ile QueryConfig derleyici tarafından sevk edilebilir hiçbir tür bilgi vermek ve sizce neden derleyici sen tipini "tahmin" olabilir geri dönecek ve tipini kontrol edecek misin?

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

Çok teşekkür ederim!Benzer bir şey deniyordum, ancak QueryConfig'in type parametresini queryMany imzasıyla özlüyordu, bu yüzden derleyici Class'tan Class 'a dönüştürme hakkında şikayette bulundu – DiegoAlfonso

İlgili konular