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