浏览 5621 次
精华帖 (0) :: 良好帖 (8) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-04-21
String getLikeCondition(String condition) { return "%" + condition + "%"; } @SuppressWarnings("unchecked") public List<Product> getProducts(final Map<String, String> conditions) { final StringBuffer hql = new StringBuffer("from Product p where 1=1"); for(String key : conditions.keySet()) { if (key.equalsIgnoreCase("name")) hql.append(" and p.name like :name"); if (key.equalsIgnoreCase("category")) hql.append(" and p.category.name like :category"); if (key.equalsIgnoreCase("priceLowerBound")) { int priceLowerBound = Integer.parseInt(conditions.get(key)); if (priceLowerBound > 0) hql.append(" and p.price > :priceLowerBound"); } if (key.equalsIgnoreCase("priceUpperBound")) { int priceUpperBound = Integer.parseInt(conditions.get(key)); if (priceUpperBound > 0) hql.append(" and p.price <= :priceUpperBound"); } //Other conditions omitted } return (List<Product>) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Query query = session.createQuery(hql.toString()); for(String key : conditions.keySet()) { if (key.equalsIgnoreCase("name")) query.setParameter("name", getLikeCondition(conditions.get("name"))); if (key.equalsIgnoreCase("category")) query.setParameter("category", getLikeCondition(conditions.get("category"))); if (key.equalsIgnoreCase("priceLowerBound")) { int priceLowerBound = Integer.parseInt(conditions.get(key)); if (priceLowerBound > 0) query.setParameter("priceLowerBound", (float)priceLowerBound); } if (key.equalsIgnoreCase("priceUpperBound")) { int priceUpperBound = Integer.parseInt(conditions.get(key)); if (priceUpperBound > 0) query.setParameter("priceUpperBound", (float)priceUpperBound); } //Other conditions omitted } List<Product> items = (List<Product>)query.list(); return items; } }); } 方法getProducts接受一个类型为Map<String, String>的参数conditions,该参数是一个<属性,属性值>列表,在方法中分析这个列表并组合成查询条件,最后执行查询并返回符合条件的Product列表 让人不爽的是代码中使用了很多if判断,而且使用了两次循环。是否有更好的办法来简化这段代码呢?或者有没有更好的方式来实现这个需求? 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-04-21
哎呀,应该发到入门讨论版的,一时手快了~~~
|
|
返回顶楼 | |
发表时间:2008-04-22
用criteria
|
|
返回顶楼 | |
发表时间:2008-04-22
我原本就是用Criteria来做的:
public List<Product> getProducts(final Map<String, String> conditions) { final DetachedCriteria query = DetachedCriteria.forClass(Product.class); for(String key : conditions.keySet()) { if (key.equalsIgnoreCase("name")) query.add(Restrictions.like(key, conditions.get(key), MatchMode.ANYWHERE)); if (key.equalsIgnoreCase("category")) query.add(Restrictions.like("category.name", conditions.get(key), MatchMode.ANYWHERE)); if (key.equalsIgnoreCase("priceLowerBound")) { int priceLowerBound = Integer.parseInt(conditions.get(key)); if (priceLowerBound > 0) query.add(Restrictions.gt("price", (float)priceLowerBound)); } if (key.equalsIgnoreCase("priceUpperBound")) { int priceUpperBound = Integer.parseInt(conditions.get(key)); if (priceUpperBound > 0) query.add(Restrictions.le("price", (float)priceUpperBound)); } //Other code omitted } //Line 22 return (List<Product>) getHibernateTemplate().execute(new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Criteria criteria = query.getExecutableCriteria(session); List<Product> items = (List<Product>)criteria.list(); return items; } }); 发现Hibernate使用了left outer join来读取关联对象,这可能导致比较严重的性能问题,所以才尝试问题中的代码。但发现使用Query来查询还是使用了left outer join来读取关联对象。找了一下资料,Criteria提供了setFetchMode方法来设置抓取模式,于是在上面代码的第22行加上如下代码: query.setFetchMode("category", FetchMode.SELECT); 果然,Hibernate使用单独的select语句来读取关联对象了(而且,如果程序中不访问这个关联对象,该条语句是不会执行的) 但似乎还是有如下两个问题: 1.如果某个关联对象没有设置fetch mode为SELECT,Hibernate还是会用left outer join读取它(就算我在查询条件中并没有使用该属性) 2.就算是设置了某关联对象的fetch mode为SELECT,但读取该关联对象的关联对象还是会用left outer join。这个太让人郁闷了:我不大可能把与Product级联关联的对象都设一下fetch mode吧? 对这两个问题,特别是第2个问题有没有好的办法来解决呢? |
|
返回顶楼 | |
发表时间:2008-04-28
关联对象的默认设置就是fetch="select",你是不是没有使用lazy loading?
|
|
返回顶楼 | |
发表时间:2008-09-10
还是用DetachedCriteria
在业务层action中设个专门的方法composeDC组织DetachedCriteria |
|
返回顶楼 | |