2017-07-15 73 views
1

我有一個@Entity類公司,它有幾個屬性,在我的db中引用一個公司表。其中一個代表一個Map companyProperties,其中公司表由company_properties表擴展,並且屬性以鍵值格式保存。JPQL在select語句中包含elementCollection地圖

@Entity 
@Table(name = "companies") 
public class Company extends AbstractEntity { 

    private static final String TABLE_NAME = "companies"; 

    @Id 
    @GeneratedValue(generator = TABLE_NAME + SEQUENCE_SUFFIX) 
    @SequenceGenerator(name = TABLE_NAME + SEQUENCE_SUFFIX, sequenceName = TABLE_NAME + SEQUENCE_SUFFIX, allocationSize = SEQUENCE_ALLOCATION_SIZE) 
    private Long id; 

    //some attributes 

    @ElementCollection 
    @CollectionTable(name = "company_properties", joinColumns = @JoinColumn(name = "companyid")) 
    @MapKeyColumn(name = "propname") 
    @Column(name = "propvalue") 
    private Map<String, String> companyProperties; 

    //getters and setters 
} 

實體管理器能夠正確地執行查找條款

Company company = entityManager.find(Company.class, companyId); 

不過,我不能在這個實體執行JPQL查詢和檢索相應的地圖。由於對象很大,我只需要在實體類中選擇一些屬性。我也不想根據companyProperties進行過濾,但是要檢索所有與合適的分配的公司ID外鍵一起使用的商品。我試圖做的是以下幾點:

TypedQuery<Company> query = entityManager.createQuery("SELECT c.id, c.name, c.companyProperties " + 
      "FROM Company as c where c.id = :id", Company.class); 
query.setParameter("id", companyId); 
Company result = query.getSingleResult(); 

的錯誤我得到的是:

java.lang.IllegalArgumentException異常: 異常說明:編譯問題[而創造的EntityManager查詢時出現異常SELECT c.id,c.name,c.companyProperties FROM Company as c where c.id =:id]。 [21,40]狀態字段路徑'c.companyProperties'不能被解析爲集合類型。 org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1616) org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1636) com.sun.enterprise.container .common.impl.EntityManagerWrapper.createQuery(EntityManagerWrapper.java:476)

試圖與加入做到這一點(我的最遠點與

Query query = entityManager.createQuery("SELECT c.id, c.name, p " + 
      "FROM Company c LEFT JOIN c.companyProperties p where c.id = :id"); 

不給我任何正確的結果(這隻返回屬性的值而不是它們的鍵值列表)

如何定義正確的查詢來執行此操作?

+0

您不能在結果子句中包含多值項目,因爲任何JPQL文檔都會告訴您 –

回答

1

您的JPA語法對我很不利。在您的第一個查詢中,您選擇了Company實體中的單個字段。但這不是JPA的工作原理;當你查詢時,你可以找回整個對象,你可以通過它訪問你想要的任何字段。我提出下面的代碼來代替:

TypedQuery<Company> query = entityManager.createQuery("from Company as c where c.id = :id", Company.class); 
query.setParameter("id", companyId); 
Company result = query.getSingleResult(); 

同樣,第二連接查詢,我建議如下代碼:

Query query = entityManager.createQuery("SELECT c" + 
     "FROM Company c LEFT JOIN c.companyProperties p WHERE c.id = :id"); 
query.setParameter("id", companyId); 
List<Company> companies = query.getResultList(); 

之所以只選擇一個Company,而不是一個性質的實體是性能會在Company類中顯示爲集合。假設公司和財產之間存在一對多關係,您可以訪問每個Company實體的屬性。

+0

我不想檢索整個實體,而僅檢索某些特定屬性。原因是,因爲最終我會返回該對象作爲休息endpoiint的結果。我不希望我的客戶端訪問所有的屬性,而是在查詢後將它們設置爲null,我期待JPQL讓我只檢索我需要的東西 –

+0

@SantiagoPerezChavez然後只要發回任何你想要的東西。無論如何,即使實體具有NULL佔位符,當您轉換爲JSON時,它仍然會浪費空間。 –

+0

如果您確實只想檢索ceetain字段,那麼您可以使用本機SQL查詢並獲取由「Object」組成的結果集。但通常在JPA中,您可以找回整個實體。 –

0

當您只在特定的字段上進行選擇時,您期望得到一個完整的Company對象,這是不可能的。如果你真的想節省一些內存(在大多數情況下不會是太大的成功),並且只選擇某些領域,那麼你應該期待一個List<Object[]>

List<Object[]> results = entityManager.createQuery("SELECT c.id, c.name, p " + 
     "FROM Company c LEFT JOIN c.companyProperties p where c.id = :id") 
     .setParameter("id", companyId) 
     .getResultList(); 

這裏results將包含在單個陣列的選定字段。您可以使用getSingleResult,但請注意,如果未找到結果,它將拋出異常。

相關問題