Использование setDate в PreparedStatement

чтобы сделать наш код более стандартным, нас попросили изменить все места, где мы жестко закодировали наши переменные SQL, на подготовленные операторы и привязать переменные.

однако я сталкиваюсь с проблемой с setDate().

вот код:

        DateFormat dateFormatYMD = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        DateFormat dateFormatMDY = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
        Date now = new Date();
        String vDateYMD = dateFormatYMD.format(now);
        String vDateMDY = dateFormatMDY.format(now);
        String vDateMDYSQL =  vDateMDY ;
        java.sql.Date date = new java.sql.Date(0000-00-00);

   requestSQL = "INSERT INTO CREDIT_REQ_TITLE_ORDER (REQUEST_ID," + 
                " ORDER_DT, FOLLOWUP_DT) " +  "values(?,?,?,)";


                prs = conn.prepareStatement(requestSQL);

                prs.setInt(1,new Integer(requestID));

                prs.setDate(2,date.valueOf(vDateMDYSQL));
                prs.setDate(3,date.valueOf(sqlFollowupDT));

я получаю эту ошибку, когда SQL выполняется:

    java.lang.IllegalArgumentException
    at java.sql.Date.valueOf(Date.java:138)
    at com.cmsi.eValuate.TAF.TAFModuleMain.CallTAF(TAFModuleMain.java:1211)

должен ли я использовать setString() вместо с to_date()?

6 ответов


Using использование java.sql.Date

если ваша таблица имеет столбец типа DATE:

  • java.lang.String

    метод java.sql.Date.valueOf(java.lang.String) получена строка, представляющая дату в формате yyyy-[m]m-[d]d. например:

    ps.setDate(2, java.sql.Date.valueOf("2013-09-04"));
    
  • java.util.Date

    Предположим, у вас есть переменная endDate типа java.util.Date, вы делаете преобразование таким образом:

    ps.setDate(2, new java.sql.Date(endDate.getTime());
    
  • настоящее

    если вы хотите вставить текущую дату:

    ps.setDate(2, new java.sql.Date(System.currentTimeMillis()));
    
    // Since Java 8
    ps.setDate(2, java.sql.Date.valueOf(java.time.LocalDate.now()));
    

Using использование java.sql.Timestamp

если ваша таблица имеет столбец типа TIMESTAMP или DATETIME:

  • java.lang.String

    метод java.sql.Timestamp.valueOf(java.lang.String) получена строка, представляющая дату в формате yyyy-[m]m-[d]d hh:mm:ss[.f...]. например:

    ps.setTimestamp(2, java.sql.Timestamp.valueOf("2013-09-04 13:30:00");
    
  • java.util.Date

    Предположим, у вас есть переменная endDate типа java.util.Date, вы делаете преобразование, таким образом:

    ps.setTimestamp(2, new java.sql.Timestamp(endDate.getTime()));
    
  • настоящее

    Если вам требуется текущая метка времени:

    ps.setTimestamp(2, new java.sql.Timestamp(System.currentTimeMillis()));
    
    // Since Java 8
    ps.setTimestamp(2, java.sql.Timestamp.from(java.time.Instant.now()));
    ps.setTimestamp(2, java.sql.Timestamp.valueOf(java.time.LocalDateTime.now()));
    

tl; dr

С JDBC 4.2 или новее и java 8 или новее:

myPreparedStatement.setObject( … , myLocalDate  )

...и...

myResultSet.getObject( … , LocalDate.class )

подробности

ответ Варгаса хорош в упоминании java.типы времени, но относится только к преобразованию в java.язык SQL.Дата. Нет необходимости конвертировать, если ваш драйвер обновлен.

java.время

на java.время framework встроен в Java 8 и более поздние версии. Эти классы вытесняют старые хлопоты классы даты и времени, такие как java.util.Date, .Calendar, & java.text.SimpleDateFormat. The Joda Времени команда также советует миграцию на java.время.

чтобы узнать больше, см. В Oracle Учебник. И search Stack Overflow для многих примеров и объяснений.

большая часть java.функциональность времени обратно портирована на Java 6 & 7 в ThreeTen-Backport и далее адаптированы к Android в ThreeTenABP.

LocalDate

на java.время java.time.LocalDate класс представляет значение только даты без времени суток и без часового пояса.

при использовании драйвер JDBC соответствуют JDBC 4.2 или более поздняя спецификация, не нужно использовать старый java.sql.Date класса. Вы можете передать/принести LocalDate объекты непосредственно в / из вашей базы данных через PreparedStatement::setObject и ResultSet::getObject.

LocalDate localDate = LocalDate.now( ZoneId.of( "America/Montreal" ) );
myPreparedStatement.setObject( 1 , localDate  );

...и...

LocalDate localDate = myResultSet.getObject( 1 , LocalDate.class );

перед JDBC 4.2 преобразовать

если ваш драйвер не может обрабатывать java.типы времени напрямую, вернуться к преобразованию в java.типы sql. Но минимизировать их использование, с вашей бизнес-логикой, используя только java.типы времени.

новые методы были добавлены к старым классам для преобразования в / из java.типы времени. Для java.sql.Date посмотреть valueOf и toLocalDate методы.

java.sql.Date sqlDate = java.sql.Date.valueOf( localDate );

...и...

LocalDate localDate = sqlDate.toLocalDate();

заполнитель стоимостью

будьте осторожны с использованием 0000-00-00 как значение заполнителя, как показано в коде вашего вопроса. Не все базы данных и другое программное обеспечение могут справиться с возвращением так далеко во времени. Я предлагаю использовать что-то вроде обычно используемого дата отсчета эпохи Unix/Posix 1970 г. 1970-01-01.

LocalDate EPOCH_DATE = LocalDate.ofEpochDay( 0 ); // 1970-01-01 is day 0 in Epoch counting.

о java.время

на java.время framework встроен в Java 8 и более поздние версии. Эти классы вытесняют беспокойных старых наследие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

на Joda Времени, теперь режим обслуживания, советует переход к java.время классы.

чтобы узнать больше, см. В Oracle Учебник. И search Stack Overflow для многих примеров и объяснений. Спецификация JSR 310.

вы можете обменять java.время объекты непосредственно с вашей базой данных. Используйте драйвер JDBC соответствуют JDBC 4.2 или позже. Нет необходимости в строках, нет необходимости в java.sql.* занятия.

где получить java.время занятий?

  • Java SE 8, Java SE 9, Java SE 10, и позже
    • встроенный.
    • часть стандартного API Java со встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и зафиксировать.
  • Java SE 6 и Java SE 7
    • большая часть java.функциональность времени обратно портирована на Java 6 & 7 в ThreeTen-Backport.
  • Android
    • более поздние версии Android bundle реализации java.время занятия.
    • для более раннего Android (ThreeTenABP проект приспосабливается ThreeTen-Backport (упоминалось выше). См.как использовать ThreeTenABP....

на ThreeTen-Extra проект расширяет java.время с дополнительными занятиями. Этот проект является испытательным полигоном для возможных будущих дополнений к Java.время. Здесь вы можете найти полезные классы, такие как Interval, YearWeek, YearQuarter и больше.


проблема заключается в том, что вы передаете несовместимые форматы из отформатированного java.утиль.Дата создания экземпляра java.sql.Date, которые не ведут себя одинаково при использовании valueOf() поскольку они используют различные форматы.

Я также вижу, что вы стремитесь сохранить часы и минуты, и я думаю, что вам лучше изменить тип данных на java.sql.Timestamp, который поддерживает часы и минуты, а также изменение поля базы данных на DATETIME или аналогичный (в зависимости от ваш поставщик базы данных).

в любом случае, если вы хотите изменить от java.util.Date to java.sql.Date, Я предлагаю использовать

java.util.Date date = Calendar.getInstance().getTime();
java.sql.Date sqlDate = new java.sql.Date(date.getTime()); 
// ... more code here
prs.setDate(sqlDate);

на docs явно говорит, что java.sql.Date кину:

  • IllegalArgumentException - если дата не указана в формате escape даты JDBC (yyyy-[m]m-[d]d)

Также вам не нужно будет конвертировать дату в String затем к sql.date, это кажется излишним (и чревато ошибками!). Вместо этого вы могли бы:

java.sql.Date sqlDate := new java.sql.Date(now.getTime());
prs.setDate(2, sqlDate);
prs.setDate(3, sqlDate);

Если вы хотите добавить текущую дату в базу данных, я бы избегал вычисления даты в Java для начала. Определение "сейчас" на стороне Java (клиента) приводит к возможным несоответствиям в базе данных, если клиентская сторона неправильно настроена, имеет неправильное время, неправильный часовой пояс и т. д. Вместо этого дату можно установить на стороне сервера следующим образом:

requestSQL = "INSERT INTO CREDIT_REQ_TITLE_ORDER ("   +
                "REQUEST_ID, ORDER_DT, FOLLOWUP_DT) " +
                "VALUES(?, SYSDATE, SYSDATE + 30)";

...

prs.setInt(1, new Integer(requestID));

таким образом, требуется только один параметр привязки и даты рассчитываются на сервере сторона будет последовательной. Еще лучше было бы добавить триггер insert в CREDIT_REQ_TITLE_ORDER и попросите триггер вставить даты. Это может помочь обеспечить согласованность между различными клиентскими приложениями (например, кто-то пытается сделать исправление через sqlplus.


Не уверен, но я думаю, что вы ищете, чтобы создать Java.утиль.Дата из строки, затем преобразуйте эту java.утиль.Дата на java.язык SQL.Дата.

попробуйте это:

private static java.sql.Date getCurrentDate(String date) {

    java.util.Date today;
    java.sql.Date rv = null;
    try {

        SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
        today = format.parse(date);
        rv = new java.sql.Date(today.getTime());
        System.out.println(rv.getTime());

    } catch (Exception e) {
        System.out.println("Exception: " + e.getMessage());
    } finally {
        return rv;
    }

}    

вернет java.язык SQL.Объект Date для setDate();

функция выше выведет длинное значение:

1375934400000