Вопрос-ответ

Using setDate in PreparedStatement

Использование 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()?

Переведено автоматически
Ответ 1

❐ Использование 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()));

❐ Использование 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()));

Ответ 2

tl; dr

С JDBC 4.2 или более поздней версии и java 8 или более поздней:

myPreparedStatement.setObject( … , myLocalDate  )

... и…

myResultSet.getObject( … , LocalDate.class )

Подробные сведения

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

java.time

Платформа java.time встроена в Java 8 и более поздние версии. Эти классы заменяют старые проблемные классы даты и времени, такие как java.util.Date, .Calendar, & java.text.SimpleDateFormat. Команда Joda-Time также рекомендует перейти на java.time.

Чтобы узнать больше, ознакомьтесь с Руководством по Oracle. И найдите в Stack Overflow множество примеров и пояснений.

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

LocalDate

В java.time класс 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.time напрямую, вернитесь к преобразованию в типы java.sql. Но сведите к минимуму их использование, поскольку в вашей бизнес-логике используются только типы java.time.

В старые классы добавлены новые методы для преобразования в / из 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.time

Платформа java.time встроена в Java 8 и более поздние версии. Эти классы заменяют старые, вызывающие беспокойство, устаревшие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Проект Joda-Time, который сейчас находится в режиме обслуживания, рекомендует перейти на классы java.time.

Чтобы узнать больше, ознакомьтесь с Руководством по Oracle. И найдите в Stack Overflow множество примеров и пояснений. Спецификация - JSR 310.

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

Где получить классы java.time?


  • Java SE 8, Java SE 9, Java SE 10 и более поздние версии

    • Встроенный.

    • Часть стандартного Java API с комплексной реализацией.

    • Java 9 добавляет некоторые незначительные функции и исправления.


  • Java SE 6 и Java SE 7

    • Большая часть функциональных возможностей java.time перенесена обратно на Java 6 и 7 в ThreeTen-Backport.


  • Android

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

Ответ 3

В документах явно сказано, что java.sql.Date выдаст:



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


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

java.sql.Date sqlDate := new java.sql.Date(now.getTime());
prs.setDate(2, sqlDate);
prs.setDate(3, sqlDate);
Ответ 4

Проблема, с которой вы сталкиваетесь, заключается в том, что вы передаете несовместимые форматы из отформатированного java.util.Дата для создания экземпляра 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);
java sql jdbc