2012-10-22 17 views
10

Jeśli moja lista jest pusta, pojawia się następujący błąd:Hibernate ograniczenie w przyczyny błędu, jeśli lista jest pusta

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 ')' 

Poniżej jest moje hibernacji związanych metoda:

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

co mam zrobić, aby uchronić się przed tym błędem?

wiem mogłyby zwierać połączenie i powrócić pustą listę takich jak:

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

Ale czy istnieje bardziej elegancki sposób to zrobić?

Odpowiedz

11

NIE. Jeśli wykonasz zapytanie z pustymi parametrami dla klauzuli in, to się nie powiedzie (możesz to sprawdzić, uruchamiając zwykły SQL). Lepiej nie wykonywać zapytania, jeśli parametr wejściowy jest pusty/pusty.

Jedyne co mogę doradzić jest użycie isEmpty() funkcję i != null w if oświadczenia i trochę restrukturyzacji jako:

@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; 
} 
2

(Jest to głównie baza na post @Yogendra Singha, o skręcie aby uczynić go bardziej adoptable do często widywanej sytuacji wielu argumentów opcjonalnych)

Interfejs API kryteriów ma na celu umożliwienie programowego napisania zapytania. Oczekuje się, że taki rodzaj funkcji dynamicznej będzie obsługiwany w kodzie.

Zwykle wykonujemy opcjonalnych kryteriów przez to:

@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(); 
} 

Edit:

Chociaż Hibernate nie (jeszcze) zapewniają bardziej elegancki sposób, na który można napisać coś samemu zrobić wygląda bardziej elegancko:

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; 
    } 
} 

Następnie możesz zrobić coś wygląda mądrzej:

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

criteriaBuilder .in("someField", listPossiblyNullOrEmpty); 


return criteriaBuilder .toCriteria().list();  
11

Powiedziałbym, że Hibernate musi naprawić ten problem i dać sensowną wiadomość.

Uważam, że odpowiedzialność dostawcy/hibernacji za sprawdzenie pustej/pustej listy.

Można sobie wyobrazić przyczynę, próbuje ona skonstruować klauzulę where, coś jak id in(), gdzieś w org.hibernate.loader.criteria.CriteriaQueryTranslator lub podobnie .. Ale ponieważ tutaj lista jest pusta, byłaby rzucając wyjątek. Ale już stworzyli zapytanie z (i nie mogą ukończyć z powodu wyjątku/pustej listy.)

Powiązane problemy