Подтвердить что ты не робот

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

4b9b3361

Ответ 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