2013-03-14 17 views
5

Mam stronę wyszukiwania z wielu kryteriów wyszukiwaniaSporządzone sprawozdanie z dynamicznym gdzie klauzula

  1. Nazwa Pracownik
  2. Pracownik Id
  3. Data przystąpienia
  4. Departament

etc

Użytkownik może zapewnić jeden lub więcej kryteria wyszukiwania. Muszę wysłać zapytanie do bazy danych, aby uzyskać wyniki wyszukiwania.

Używając zwykłego JDBC, są dwie możliwości osiągnięcia tego.

  1. Przygotuj zapytanie SQL, dodając kryteria wyszukiwania podane przez użytkownika.

Np

String selectClause = "SELECT * FROM EMPLOYEES WHERE "; 
String whereClause = ""; 
if(StringUtils.isNotBlank(empName)){ 
    if(whereClause.length > 0){ 
     whereClause += " AND "; 
    } 
    selectQuery += " EMP_NAME = " + empName; 
} 
if(StringUtils.isNotBlank(empID)){ 
    if(whereClause.length > 0){ 
     whereClause += " AND "; 
    } 
    selectQuery += " EMP_ID = " + empID; 
} 
//... and so on ... 
  1. Stosując preparestatement

ex:

String query = "SELECT * FROM EMPLOYEES WHERE EMP_NAME = ? AND EMP_ID = ? DATE_OF_JOINING = ? AND DEPARTMENT = ?"; 

to answer wyjaśnia, że ​​tak jak wirnik przykł 1 powyżej, ex2 można zmodyfikować, podobnie jak poniżej

String selectClause = "SELECT * FROM EMPLOYEES WHERE "; 
String whereClause = ""; 
if(StringUtils.isNotBlank(empName)){ 
    if(whereClause.length > 0){ 
     whereClause += " AND "; 
    } 
    selectQuery += " EMP_NAME = ?"; 
} 
if(StringUtils.isNotBlank(empID)){ 
    if(whereClause.length > 0){ 
     whereClause += " AND "; 
    } 
    selectQuery += " EMP_ID = ?"; 
} 
//... and so on ... 

Następnie ostrożnie (zachowując indeks parametrów na uwadze) wejście musi zostać ustawione na przygotowaną instrukcję. To nie brzmi jak idealne rozwiązanie.

Czy można to zrobić w elegancki sposób (bez frameworków ORM)?

+3

Twoje pierwsze podejście może * łatwo * prowadzić do ataków typu SQL injection, jeśli nie jesteś bardzo ostrożny. –

Odpowiedz

3

Nie chciałbym używać do dynamicznego tworzenia zapytań za każdym razem, szczególnie gdy liczba znaczących kombinacji jest policzalna i skończona.

Zawsze wolałbym struny statyczne. Tak, musisz je wpisać, ale zrobisz to raz. Wolałbym to zrobić niż zapłacić cenę w złożoności iw czasie działania.

+3

Masz na myśli, że powinienem mieć gotowe zapytania statyczne dla każdej kombinacji danych wejściowych? Obecnie mam cztery wejścia, więc zapytania o połączenie czterech wejść? Idąc dalej, może być więcej danych wejściowych. Czy to nie będzie kompletne? – Apurv

+0

Tak, wpiszę je. Powiedziałbym, że maszynistka dotykowa może znaleźć 10 zapytań bez większych problemów. Wszystkie kombinacje nie są jednakowe. Powiedziałbym, że lepiej byłoby pomyśleć o tych, które użytkownicy najprawdopodobniej naprawdę wykorzystają i po prostu zaimplementować je raz statycznie jako PreparedStatements. Prawdopodobnie mógłbyś je zakodować w czasie, który zajmuje debatę nad odpowiedzią tutaj. – duffymo

+0

Czy nie będzie niesprawiedliwe, że mój pracodawca nie zastosuje się do zalecanego podejścia? – Apurv

5

W takich warunkach wolę dodawać 1=1 w klauzuli where, tak aby nie trzeba było śledzić, gdzie wstawić AND.

String selectClause = "SELECT * FROM EMPLOYEES WHERE 1=1 "; 
if(StringUtils.isNotBlank(empName)){ 
    selectQuery += "AND EMP_NAME = " + empName; 
} 
if(StringUtils.isNotBlank(empID)){ 
    selectQuery += "AND EMP_ID = " + empID; 
} 
//... and so on ... 

Powiązane question.

+0

Mimo że 1 = 1 jest bardzo wygodnym sposobem dodawania wszystkich elementów "ORAZ", należy pamiętać, że niektóre silniki/optymalizatory RDBMS działają lepiej, a wydajność zapytań może być bardzo zła. Dodaję wszystkie warunki do listy i łączę je z AND. Coś jak 'String whereClause = StringUtils.join (warunkiList," AND ");' – Yogi

+0

@xyz Co jeśli mamy pewien warunek z klauzulą ​​'OR' również? – Piyush

+0

@Piyush następnie użyj 'OR' zamiast' AND' jak 'selectQuery + =" OR .. ' – xyz

2

Łatwo to zrobić bez żadnej złożonej i kosztownej logiki, w jednej linii ...

Zakładając, że trzy zmienne są @name, @surname i @gender.

Zakładając również, że łańcuch o zerowej długości zostanie dostarczony, gdy filtr nie jest wymagany.

Następnie Twój Wybierz stwierdzenie jest po prostu:

select * from table_name where (name = @name or @name = '') and (surname = @surname or @surname = '') and (gender = @gender or @gender = '') 

To wszystko na ten temat! Bez skomplikowanej i kosztownej logiki.

+0

Czy jest to instrukcja przygotowana przez JDBC? Co jest generowane przez SQL, jeśli nazwa nie jest wymaganym parametrem ? – andyd