在PreparedStatement中使用setDate

为了使我们的代码更加标准化,我们被要求将我们的SQLvariables硬编码为SQL语句的所有地方改为准备语句,然后绑定variables。

不过,我正面临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()

❐使用java.sql.Date

如果你的表有一个DATEtypes的列:

  • java.lang.String

    java.sql.Date.valueOf(java.lang.String)方法接收到一个string,表示格式为yyyy-[m]m-[d]d 。 例如:

     ps.setDate(2, java.sql.Date.valueOf("2013-09-04")); 
  • java.util.Date

    假设你有一个types为java.util.Date的variablesendDate ,你可以这样进行转换:

     ps.setDate(2, new java.sql.Date(endDate.getTime()); 
  • 当前

    如果你想插入当前date:

     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

如果您的表有一个TIMESTAMPDATETIMEtypes的列:

  • java.lang.String

    java.sql.Timestamp.valueOf(java.lang.String)方法接收到表示date的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

    假设你有一个types为java.util.Date的variablesendDate ,你可以这样进行转换:

     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;博士

 myPreparedStatement.setObject( … , myLocalDate ) 

…和…

 myResultSet.getObject( … , LocalDate.class ) 

细节

Vargas的答案是提到java.timetypes,但只涉及转换为java.sql.Date。 如果您的驱动程序已更新,则无需转换。

java.time

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

要了解更多信息,请参阅Oracle教程 。 并search堆栈溢出了很多例子和解释。

大部分的java.timefunction在ThreeTen- Backport中被移植到Java 6&7中,并在ThreeTenABP中进一步适应Android。

LocalDate

在java.time中, java.time.LocalDate类表示没有时间和没有时区的只有date的值。

如果使用符合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.timetypes,请回退到转换为java.sqltypes。 但是最小化它们的使用,只使用java.timetypes的业务逻辑。

新的方法已被添加到旧的类转换为/从java.timetypes。 对于java.sql.Date请参阅valueOftoLocalDate方法。

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

…和…

 LocalDate localDate = sqlDate.toLocalDate(); 

占位符值

请谨慎使用作为您的问题代码中显示的占位符值。 并不是所有的数据库和其他软件都能及时处理。 我build议使用像1970年,1970年1月1 1970-01-01用的Unix / Posix时代的参考date 。

 LocalDate EPOCH_DATE = LocalDate.ofEpochDay( 0 ); // 1970-01-01 is day 0 in Epoch counting. 

你遇到的问题是,你从一个格式化的java.util.Date传递不兼容的格式来构造一个java.sql.Date的实例,当使用valueOf()它们的行为不同,因为它们使用不同的格式。

我也可以看到你的目标是持续时间和分钟,而且我认为你最好把数据types改为java.sql.Timestamp ,它支持小时和分钟,并且把你的数据库字段改为DATETIME或类似的(取决于您的数据库供应商)。

无论如何,如果你想从java.util.Date to java.sql.Date更改java.util.Date to java.sql.Date ,我build议使用

 java.util.Date date = Calendar.getInstance().getTime(); java.sql.Date sqlDate = new java.sql.Date(date.getTime()); // ... more code here prs.setDate(sqlDate); 

该文档明确指出, java.sql.Date将抛出:

  • IllegalArgumentException – 如果给定的date不是JDBCdate转义格式( yyyy-[m]m-[d]d

你也不需要把date转换成String然后转换成sql.date ,这似乎是多余的(并且容易出错)。 相反,您可以:

 java.sql.Date sqlDate := new java.sql.Date(now.getTime()); prs.setDate(2, sqlDate); prs.setDate(3, sqlDate); 

如果要将当前date添加到数据库中,我将避免在Java中计算date。 如果客户端configuration错误,时间错误,时区错误等,在Java(客户端)上确定“现在”会导致数据库中可能的不一致。相反,date可以在服务器端设置为方式如下:

 requestSQL = "INSERT INTO CREDIT_REQ_TITLE_ORDER (" + "REQUEST_ID, ORDER_DT, FOLLOWUP_DT) " + "VALUES(?, SYSDATE, SYSDATE + 30)"; ... prs.setInt(1, new Integer(requestID)); 

这样,只需要一个绑定参数,并且在服务器端计算date将是一致的。 更好的做法是将一个插入触发器添加到CREDIT_REQ_TITLE_ORDER并让触发器插入date。 这可以帮助强化不同客户端应用程序之间的一致性(例如,有人试图通过sqlplus进行修复。

不知道,但我认为你正在寻找的是从string创build一个java.util.Date,然后将该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; } } 

将为setDate()返回一个java.sql.Date对象;

上面的function会打印出一个长长的值:

1375934400000