2016-08-19 53 views
11

我有以下的持久類:使用Hibernate的標準地圖中的過濾鍵和值

public class Code { 

    @ElementCollection(targetClass = CodeValue.class) 
    @MapKeyClass(CodeProperty.class) 
    @JoinTable(name="code_properties") 
    @CreateIfNull(value = false) 
    private Map<CodeProperty,CodeValue> propertiesMap = 
     new HashMap<CodeProperty, CodeValue>(); 

    ... 
} 

public class CodeProperty { 
    private String name; 
    ... 
} 

public class CodeValue { 
    private String value; 
    ... 
} 

而我試圖讓一些性質我propertiesMap在過濾代碼列表(例如其中,財產名爲「顏色」的碼的值是「綠色」

我用下面的底座標準:

Criteria criteria = currentSession() 
    .createCriteria(Code.class, "code") 
    .setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); 

當我嘗試執行收集過濾器(如建議here):

criteria.createAlias("code.properties", "p"); 
criteria.add(Restrictions.eq("p.foo", "test1")); 
criteria.setFetchMode("code.properties", FetchMode.JOIN); 
criteria.list(); 

我得到以下錯誤:

org.hibernate.QueryException: could not resolve property: foo of: com.example.CodeValue 

這意味着,我真的不明白爲什麼,Hibernate是考慮到code.properties地圖CodeValue代替!

我也嘗試訪問這個字段而不創建別名,並且這種方式冬眠似乎訪問了正確的代碼類。我用properties.indeces(如建議here):

criteria.add(Restrictions.eq("properties.indeces", "foo")); 
criteria.list(); 

但有了這個,我得到了以下錯誤:

could not resolve property: properties.indeces of: com.example.Code 

有人可以幫助我瞭解什麼是錯?正確的標準查詢將以綠色找到代碼是什麼?您可以結帳the Github project that demonstrates this problem

感謝

+0

我注意到你正在使用@MapKeyClass的JPA 2.1特性。您是否一定會使用棄用的Hibernate Criteria API而不是JPA Criteria API? – Naros

+0

@Naros代表micdcar回答 - 是的,不幸的是,這意味着將整個sessionfactory配置切換到entitymanager,這可以被探索,但不會在如此短的時間內發佈。因此,我們必須創建標準,它返回一個休眠條件。 – mmalmeida

回答

1

我不相信你可以與遺留Hibernate API的標準做到這一點,有一個與使用JPA標準API Hibernate的實現一個小的限制。解決的方法之一是:

直接查詢該實體與謂語的要求得到一個List<CodeProperty>

List<CodeProperty> propertyKeys = entityManager 
    .createQuery("FROM CodeProperty p WHERE p.name = :name") 
    .setParameter("name", "foo") 
    .getResultList(); 

查詢使用JPA標準的Code實體。

// setup the query 
CriteriaBuilder cb = entityManager.getCriteriaBuilder(); 
CriteriaQuery<Code> query = cb.createQuery(Code.class); 
Root<Code> root = query.from(Code.class); 
MapJoin<Code, CodeProperty, CodeValue> mapRoot = root.joinMap("propertiesMap"); 
query.select(root).where(mapRoot.key().in(propertyKeys)); 

// get results 
List<Code> results = entityManager.createQuery(query).getResultList(); 

我試着用這些來組合:

query 
    .select(root) 
    .where (cb.eq(mapRoot.key().get("name"), "foo")) 

問題是這樣導致NotYetImplemented例外:(。

1

請確認您是否使用過的indeces曾在預測問題或指數。正確的用法如下:

criteria.createAlias("code.properties", "p"); 
criteria.add(Restrictions.eq("p.indices", "foo")); 
criteria.list(); 

或者,您可以在限制使用

eq("p." + CollectionPropertyNames.COLLECTION_INDICES) 

請讓我知道它是否仍然不適合你。

1

您的方法存在各種問題: 在您的項目中觀看MapTest文件夾github我建議您始終將變量名稱作爲列名稱,並在條件中使用這些相同的名稱。 標準是地圖,其第一個參數是屬性名稱,第二個參數是屬性值。 對於多對多的關係,你可以嘗試使用:

@JoinTable(
     name="docente_classe", 
     joinColumns= 
      @JoinColumn(name="id_dipendente", referencedColumnName="id_dipendente"), 
     inverseJoinColumns= 
      @JoinColumn(name="id_classe", referencedColumnName="id_classe") 
) 

這是JPA註解,我不知道這是否編譯您的項目。

https://github.com/tredue1/School_Manager/blob/master/code/SM/src/main/java/agc2/it/sm/gestioneDocente/DocenteJpa.java

對於查詢的多對多的關係看這個帖子:

jpa criteria for many to many relationship

+0

對不起,我沒跟着。你的例子沒有任何地圖。 查詢通過集合實現多對多是不同的事情。 您能否使用GitHub示例(或項目分支)來澄清您的答案? – mmalmeida

+0

你有沒有嘗試檢查鏈接:http://stackoverflow.com/questions/8135612/jpa-criteria-for-many-to-many-relationship ????這是一個很好的例子。 – pioardi