请问该如何优化这段逻辑:根据搜索条件查找相应的对象实体

[复制链接]
查看11 | 回复2 | 2007-10-20 08:38:44 | 显示全部楼层 |阅读模式
有一个简单的需求:Product是一个实体类,用户在搜索页面上输入Product的属性值,系统根据这些属性值找到符合条件的Product并列举出来。搜索的代码如下:
Java代码
String getLikeCondition(String condition) {
return "%" + condition + "%";
}
@SuppressWarnings("unchecked&quot


public List getProducts(final Map conditions) {
final StringBuffer hql = new StringBuffer("from Product p where 1=1&quot

;
for(String key : conditions.keySet()) {
if (key.equalsIgnoreCase("name&quot

)

hql.append(" and p.name like :name&quot

;
if (key.equalsIgnoreCase("category&quot

)

hql.append(" and p.category.name like :category&quot

;
if (key.equalsIgnoreCase("priceLowerBound&quot

) {

int priceLowerBound = Integer.parseInt(conditions.get(key));

if (priceLowerBound > 0)

hql.append(" and p.price >

riceLowerBound&quot

;
}
if (key.equalsIgnoreCase("priceUpperBound&quot

) {

int priceUpperBound = Integer.parseInt(conditions.get(key));

if (priceUpperBound > 0)

hql.append(" and p.price ) 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 items = (List)query.list();

return items;
}
});
}
回复

使用道具 举报

千问 | 2007-10-20 08:38:44 | 显示全部楼层
哎呀,应该发到入门讨论版的,一时手快了~~~
回复

使用道具 举报

千问 | 2007-10-20 08:38:44 | 显示全部楼层
我原本就是用Criteria来做的:
Java代码
public List getProducts(final Map 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) getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {

Criteria criteria = query.getExecutableCriteria(session);

List items = (List)criteria.list();

return items;
}
});

public List getProducts(final Map 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) getHibernateTemplate().execute(new HibernateCallback() {

public Object doInHibernate(Session session) throws HibernateException {

Criteria criteria = query.getExecutableCriteria(session);

List items = (List)criteria.list();

return items;

}

});

发现Hibernate使用了left outer join来读取关联对象,这可能导致比较严重的性能问题,所以才尝试问题中的代码。但发现使用Query来查询还是使用了left outer join来读取关联对象。找了一下资料,Criteria提供了setFetchMode方法来设置抓取模式,于是在上面代码的第22行加上如下代码:
Java代码
query.setFetchMode("category", FetchMode.SELECT);
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个问题有没有好的办法来解决呢?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行