Использование 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
❐ 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());
-
Current
Если вы хотите вставить текущую дату:
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()));
-
Current
Если вам нужна текущая временная метка:
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
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. И поиск Qaru для многих примеров и объяснений.
Большая часть функций 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.time. Для 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.
Ответ 3
Проблема, с которой вы сталкиваетесь, заключается в том, что вы передаете несовместимые форматы из форматированного java.util.Date, чтобы создать экземпляр 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);
Ответ 4
docs явно говорит, что java.sql.Date
будет бросать:
-
IllegalArgumentException
- если указанная дата не находится в формате выхода даты 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);
Ответ 5
Если вы хотите добавить текущую дату в базу данных, я бы не стал вычислять дату на 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));
Таким образом, требуется только один параметр привязки и даты, рассчитанные на стороне сервера, будут согласованы. Еще лучше добавить триггер вставки в CREDIT_REQ_TITLE_ORDER
и включить триггер. Это может помочь обеспечить согласованность между различными клиентскими приложениями (например, кто-то пытается выполнить исправление через sqlplus.
Ответ 6
Не уверен, но я думаю, что вам нужно создать java.util.Date из String, а затем преобразовать этот java.util.Date в java.sql.Date.
попробуйте следующее:
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