19

如果我的列表为空,我会收到以下错误:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ')'

下面是我的hibernate相关方法:

  @Override
    public List<SomeThing> findByIds(List<Integer> someIds) {
        return sessionFactory.getCurrentSession().createCriteria(SomeClass.class)
                .add(Restrictions.in("id", someIds))
                .list();
    }

我应该怎么做才能防止这个错误?

我知道我可以将呼叫短路并返回一个空列表,例如:

if(someIds == null || someIds.size() == 0) {
  return new List<SomeThing>();
}

但是有没有更优雅的方法来做到这一点?

4

3 回答 3

17

我会说 Hibernate 需要解决这个问题,并给出有意义的信息。

我认为提供者/休眠检查空/空列表的责任。

原因可想而知,它试图构造 where 子句,例如 id in (),org.hibernate.loader.criteria.CriteriaQueryTranslator 或类似的某个地方。但是因为这里的 List 是空的,所以会抛出异常。但是他们已经使用 ( 创建了查询,并且由于异常/空列表而无法完成。

于 2012-10-22T06:21:55.700 回答
17

不。如果您使用空参数 forin子句执行查询,它将失败(您可以通过运行普通 SQL 来验证这一点)。如果输入参数为空/空,最好不要执行查询。

我唯一能建议的是使用isEmpty()函数和语句,并!= null进行if少量重组:

@Override
public List<SomeThing> findByIds(List<Integer> someIds) {
   List<Something> result = null; //you may initialize with empty list
   if(someIds != null || !someIds.isEmpty() {
       result = sessionFactory.getCurrentSession().createCriteria(SomeClass.class)
            .add(Restrictions.in("id", someIds))
            .list();
   } 
   return result;
}
于 2012-10-22T03:24:00.667 回答
2

(这主要基于@Yogendra Singh 的回复,稍加改动以使其更适用于多个可选参数的常见情况)

Criteria API 旨在让您以编程方式编写查询。这种动态特性预计将在您的代码中处理。

通常我们通过以下方式制定可选标准:

@Override
public List<SomeThing> findBySearchParams(SearchParam searchParam) {
   // create criteria with mandatory search criteria
   Criteria criteria = sessionFactory.getCurrentSession()
                           .createCriteria(SomeClass.class);
                           .add(Restriction("someField", searchParam.getSomeField()));


   // add "id" only if "someId" contains value
   if(searchParam.getSomeIds() != null && !searchParam.getSomeIds().empty()) {
       criteria.add(Restrictions.in("id", searchParam.getSomeIds()));
   } 

   // add "anotherField" only if "anOptionalField" is not null
   if(searchParam.getAnOptionalField() != null) {
       criteria.add(Restrictions.in("anotherField", searchParam.getAnOptionalField()));
   } 

   return criteria.list();
}

编辑:

尽管 Hibernate (还)没有为此提供更优雅的方式,但您可以自己编写一些东西来让它看起来更优雅:

class SmartCriteriaBuilder {
  private Criteria criteria;
  SmartCriteriaBuilder (Criteria criteria) { this.criteria = criteria;}

  SmartCriteriaBuilder in(String field, Collection values) {
    if (!empty(values)) {
      this.criteria.add(Restrictions.in(field,values));
    }
  }
  // all other kind of restrictions ....

  Criteria toCriteria() {
    return this.criteria;
  }
}

然后你可以做一些看起来更聪明的事情:

SmartCriteriaBuilder criteriaBuilder = 
    new SmartCriteriaBuilder(sessionFactory.getCurrentSession().createCriteria());

criteriaBuilder .in("someField", listPossiblyNullOrEmpty);


return criteriaBuilder .toCriteria().list();    
于 2012-10-22T04:29:55.723 回答