我原本就是用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个问题有没有好的办法来解决呢? |