Nienawidzę JDBC

Kod:

public int myMethod(String day) throws SQLException{
  String sql = "Select count(*) from MyTable WHERE someColumn = ? ";
  Connection connection = ConnFactory.get();
  PreparedStatement prepareStatement = null;
  ResultSet resultSet = null;
  int ret = -1;
  try{
      prepareStatement = connection.prepareStatement(sql);
      prepareStatement.setString(1, day);
      resultSet = prepareStatement.executeQuery(sql);
      if(resultSet.next()){
          ret = resultSet.getInt(1);
      }
  }
  catch(SQLException sqle){
      // closing statement & ResultSet, log and throw exception
  }
  finally{
     // closing statement & ResultSet
  }
  ConnFactory.kill(connection);

  return ret;
}

Wynik wywołania 0. Prawidłowy wynik około 100. Jeżeli usunę klauzulę WHERE to zaczyna zwracać prawidłowe wyniki. Czy ktoś może mi powiedzieć dlaczego się tak dzieje?

13 Responses to “Nienawidzę JDBC”

  1. Sharpek Says:

    A nie jest tak że poprostu robisz błędy SQL, sprawdzałeś go jak on wygląda toString ?
    Jaka baza danych ?

  2. KosQX Says:

    A to nie jest jakiś problem z formatem daty? Może wysyłasz bazie (zmienna day) '1 październik 2009' lub '01-10-2009' a baza oczekuje '2009-10-01'?

  3. regdos Says:

    Błędny warunek WHERE. Nie ma czegoś takiego jak “kolumna=?”

  4. Koziolek Says:

    @Sharpek, pisanie SQLek zaczynam zazwyczaj od SQLdevelopera i jak tam rusza to przenoszę do kodu. W SQDdevie działało.

    @KosQX, zmienna ma prawidłowy format, YYYYMMDD i raczej innego nie da się tam wpuścić, bo by mi walidator odwalił.

    @regdos, niestety jest. Jeżeli używasz PrepareStatement to możesz tak jak w powyższym kodzie wstawić znaki zapytania, a następnie wywołać metodę setXXX(int, XXX), gdzie XXX to typ danych lub Object, w celu ustawienia wartości tego pola. To jest taki myk, którego chyba nie ma w php i pozwala we w miarę prosty sposób zabezpieczyć się przed SQL Injection.

    Baza Oracle 10g + driver OJDBC14.

  5. Mekk Says:

    Jeśli to Oracle, to bardzo zdecydowanie radzę napisać jakieś

    TO_DATE(?, ‘YYYY-MM-DD’)

    Choć problem węszę najbardziej w czymś innym: czy aby kolumna w bazie nie jest datą z czasem? Może nic nie znajdujesz ze względu na godziny i minuty…

    Aha: różnice w działaniu między developerem a programem mogą wynikać ze środowiska (ustawienia językowe w szczególności).

  6. Koziolek Says:

    @Mekk, też nie to. Kolumna ma typ Number.

  7. xis Says:

    Jeśli someColumn ma typ Number to może spróbuj: prepareStatement.setInt(1, Integer.parseInt(day));
    ?

  8. Koziolek Says:

    Coś jest strasznie popieprzone z bazą… jakieś wiszące transakcje dla niektórych rekordów… akurat tych na których testowałem… kuźwa… a i tak nienawidzę JDBC.

  9. Grzegorz Says:

    może poszukaj wsparcia w firmie, która dostarczyła Ci oprogramowanie… chyba że Sam sobie dostarczyłeś ;-)

    pozdrawiam,
    gzat

  10. Koziolek Says:

    @Grzegorz, niestety korzystamy z legacy kodu i nie za bardzo mamy możliwość dopisania czegoś w JPA. Zatem muszę się bawić w ten sposób.

  11. Rysand Says:

    Mieliśmy kiedyś podobne problemy na iSeries (AS400, baza 5.4).
    Proponuję:
    1. SELECT COUNT(*) AS RES FROM TABLE WHERE COL = ?
    rs.getInt(“RES”) – czasem pomaga

    1.a. SELECT COUNT(PK_COL) AS RES FROM TABLE WHERE COL = ?

    2. setString(data.trim()) – JDBC czasem wie lepiej jaki jest typ danych

    3. zgodnie z jedną z powyższych podpowiedzi – użyj dokładnie takiego samego typu danych. W PreparedStatement można podejrzeć inspektorem (debug) faktyczne zapytanie – może to pomoże.

  12. syllepsa Says:

    A czy możesz podejrzeć w logach serwera db jakie zapytanie jest do niego wysyłane?

  13. syllepsa Says:

    Jeszcze coś mi przyszło do głowy… Czy w warunku ustawiasz dni tygodnia? Jeśli tak to może ustawiasz złe wartości dla zmiennej day? Calendar.SUNDAY=1, Calendar.MONDAY=2. To tylko takie moje gdybanie…

Leave a Reply