Использование 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
- Более поздние версии Android bundle реализуют классы java.time.
- Для более ранних версий Android (<26) проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше). Смотрите , как использовать ThreeTenABP ....
Проект 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);