2009-09-30 49 views
1

我有一個使用JPA的Java應用程序。如何最好地處理列表<Entity>,列表<Entity Id>,列表<Entity name>有效?

說我有叫Productnameprice屬性(所有實體有一個id屬性)的實體。

當然,我可以得到一個List<Product>很容易(從查詢或其他實體),但我常常想List<String>(產品名稱的列表)或List<Long>(產品價格或產品ID列表的列表)。

很多它一樣容易繞過整個Product,但有兩種情況下,我並不想這樣做的時候:

  • 我傳遞列表的一類它不應該依賴於Product類。
  • 獲取ID列表比完整的產品對象要容易得多(但在某些情況下,我已經擁有它們)。

用簡單的方式來做到這一點會去是這樣的:

List<Long> productIds = new ArrayList<Long>(); 
for(Product product: products) { 
    productIds.add(product.getId()); 
} 

但我不喜歡這個,因爲它的混亂和低效。在蟒蛇我會做這樣的事情:

[ p.id for p in products ] 

「最佳」 我可以在Java想出是:

public class ProductIdList extends AbstractList<Long> { 
    private List<Product> data; 

    public ProductIdList(List<Product> data) { 
    this.data = data; 
    } 

    public Long get(int i) { 
    return data.get(i).getId(); 
    } 

    public int size() { 
    return data.size(); 
    } 

    public Long remove(int i) { 
    return data.remove(i).getId(); 
    } 

    /* For better performance */ 
    public void clear() { 
    data.clear(); 
    } 

    /* Other operations unsupported */ 
} 

優點:

  • 這種方法不需要複製數據
  • 這是對數據的真實「視圖」 - 反映了對基礎列表的更改。

缺點:

  • 好像很多的代碼
  • 需要這樣一類爲每個屬性我要像這樣訪問

因此,這是一個很好的想法與否?我應該在大部分時間創建次要列表嗎?有沒有第三個選項我沒有考慮?

+0

把評論不一個答案。只是一個小小的提示,你總是可以獲取產品ID,而不是整個產品(使用我聽說過的標量查詢)。例如。 SELECT prod.id FROM Product prod ... – 2009-09-30 12:13:25

+0

無誤。也許我應該更清楚。有時候我可以做到這一點,而且沒有問題。有時我已經有一個名單,不想重新查詢。 – Draemon 2009-09-30 12:17:17

+0

您可以使用一個具有每種屬性一種方法的類。至少會減少一個CONS。 – StampedeXV 2009-09-30 14:34:25

回答

1

您可以通過讓它們從具有getAttribute方法的抽象類繼承來最小化這些每個屬性包裝類的大小。事情是這樣的:

public abstract class AbstractProductList<T> extends AbstractList<T> { 
    protected List<Product> data; 

    public AbstractProductList(List<Product> data) { 
    this.data = data; 
    } 

    protected abstract T getAttribute(Product product); 

    public T get(int i) { 
    return getAttribute(data.get(i)); 
    } 

    public int size() { 
    return data.size(); 
    } 

    public T remove(int i) { 
    return getAttribute(data.remove(i)); 
    } 

    /* For better performance */ 
    public void clear() { 
    data.clear(); 
    } 

    /* Other operations unsupported */ 
} 

public class ProductIdList extends AbstractProductList<Long> { 
    public ProductIdList(List<Product> data) { 
    super(data); 
    } 

    protected Long getAttribute(Product product) { 
    return product.getId(); 
    } 
} 
+0

我喜歡這個。我認爲產品類也可以是通用的。 – Draemon 2009-09-30 15:30:21

0

您可以使用一個對每個屬性使用一個方法的Class。至少會減少一個CONS。

這是你的例子與我的建議調整。

public class ProductList { 
    private List<Product> data; 

    public ProductIdList(List<Product> data) { 
    this.data = data; 
    } 

    public Long getId(int i) { 
    return data.get(i).getId(); 
    } 

    public List<String> getProductNames(int i) { 
    return data.get(i).getProductNames(); 
    } 

    public Product getProduct(int i) { 
    return data.get(i); 
    } 

    public int size() { 
    return data.size(); 
    } 

    public Long remove(int i) { 
    return data.remove(i).getId(); 
    } 

    /* For better performance */ 
    public void clear() { 
    data.clear(); 
    } 
} 
+0

這不會實現列表,所以它不能用於預期列表的地方。 – Draemon 2009-09-30 15:31:18

3

只是在另一種可能性扔,你可以使用Apache的百科全書變壓器和收集創建一個新的集合或變換修改現有的一個:

Collection<Long> productIds = CollectionUtils.collect(products, new Transformer() { 
     public Long transform(Object o) { 
      return ((Product) o).id; 
     } 
    }); 
+0

這可能是實現我想要的最正確的方法。不幸的是,Commons還沒有趕上泛型,所以和額外的圖書館意味着我不能證明它。仍然是+1 – Draemon 2009-09-30 16:06:59

相關問題