2009-09-30 73 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