在 PreparedStatement 中使用 setDate

新手上路,请多包涵

为了使我们的代码更加标准,我们被要求将我们硬编码 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() 吗?

原文由 roymustang86 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

❐ 使用 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

如果您的表有一列类型为 TIMESTAMPDATETIME

  • 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()));

原文由 Paul Vargas 发布,翻译遵循 CC BY-SA 3.0 许可协议

tl;博士

使用 JDBC 4.2 或更高版本以及 java 8 或更高版本:

 myPreparedStatement.setObject( … , myLocalDate  )

…和…

 myResultSet.getObject( … , LocalDate.class )

细节

Vargas 的答案很好地提到了 java.time 类型,但仅指转换为 java.sql.Date。如果您的驱动程序已更新,则无需转换。

java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了旧的麻烦的日期时间类,例如 java.util.Date.Calendarjava.text.SimpleDateFormatJoda-Time 团队还建议迁移到 java.time。

要了解更多信息,请参阅 Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。

许多 java.time 功能在 ThreeTen- Backport 中向后移植到 Java 6 和 7,并在 ThreeTenABP 中 进一步适应 Android。

LocalDate

在 java.time 中, java.time.LocalDate 类表示没有时间和时区的仅日期值。

如果使用符合 JDBC 4.2 或更高版本规范的 JDBC 驱动程序,则无需使用旧的 java.sql.Date 类。您可以通过 PreparedStatement::setObjectResultSet::getObject 直接将 LocalDate 对象传递/获取数据库。

 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 参见 valueOftoLocalDate 方法。

 java.sql.Date sqlDate = java.sql.Date.valueOf( localDate );

…和…

 LocalDate localDate = sqlDate.toLocalDate();

占位符值

小心使用 0000-00-00 作为占位符值,如您的问题代码中所示。并非所有数据库和其他软件都可以处理这么久的回溯。我建议使用类似于 1970 年的常用 Unix/Posix 纪元参考日期 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.DateCalendarSimpleDateFormat

现在处于 维护模式Joda-Time 项目建议迁移到 java.time 类。

要了解更多信息,请参阅 Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是 JSR 310

您可以直接与您的数据库交换 java.time 对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要 java.sql.* 类。

从哪里获得 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可能会在这里找到一些有用的类,例如 IntervalYearWeekYearQuarter 等等

原文由 Basil Bourque 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题