在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
如果你的表有一个DATE
types的列:
-
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
如果您的表有一个TIMESTAMP
或DATETIME
types的列:
-
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
, .Calendar
和java.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::setObject
和ResultSet::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
请参阅valueOf
和toLocalDate
方法。
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