为了使我们的代码更加标准化,我们被要求将我们将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()
吗?
答案 0 :(得分:127)
java.sql.Date
如果您的表格中有DATE
类型的列:
<强> java.lang.String
强>
方法java.sql.Date.valueOf(java.lang.String)
收到一个字符串,表示格式为yyyy-[m]m-[d]d
的日期。 e.g:
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
如果您的表格中包含TIMESTAMP
或DATETIME
类型的列:
<强> java.lang.String
强>
方法java.sql.Timestamp.valueOf(java.lang.String)
收到一个字符串,表示格式为yyyy-[m]m-[d]d hh:mm:ss[.f...]
的日期。 e.g:
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()));
答案 1 :(得分:15)
使用JDBC 4.2或更高版本以及Java 8或更高版本:
myPreparedStatement.setObject( … , myLocalDate )
...和...
myResultSet.getObject( … , LocalDate.class )
Vargas的回答很好地提到了java.time类型,但仅指转换为java.sql.Date。如果您的驱动程序已更新,则无需转换。
java.time框架内置于Java 8及更高版本中。这些类取代了旧的麻烦日期时间类,例如java.util.Date
,.Calendar
和&amp; java.text.SimpleDateFormat
。 Joda-Time团队还建议迁移到java.time。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。
大部分java.time功能都被反向移植到Java 6&amp; ThreeTen-Backport中的7,并在ThreeTenABP中进一步适应Android。
LocalDate
在java.time中,java.time.LocalDate
类表示没有时间且没有时区的仅限日期的值。
如果使用符合JDBC driver或更新规范的JDBC 4.2,则无需使用旧的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 );
如果您的驱动程序无法直接处理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
作为占位符值,如问题代码中所示。并非所有数据库和其他软件都能及时处理。我建议使用1970年常用的Unix/Posix epoch reference date 1970-01-01
之类的东西。
LocalDate EPOCH_DATE = LocalDate.ofEpochDay( 0 ); // 1970-01-01 is day 0 in Epoch counting.
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和&amp; SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 2 :(得分:3)
您遇到的问题是您从格式化的java.util.Date传递不兼容的格式以构造java.sql.Date
的实例,这些实例在使用{{1}时的行为方式不同因为他们使用不同的格式。
我也可以看到你的目标是坚持几小时和几分钟,我认为你最好将数据类型更改为valueOf()
,它支持小时和分钟,同时将数据库字段更改为DATETIME或类似的(取决于您的数据库供应商)。
无论如何,如果你想从java.sql.Timestamp
改变,我建议使用
java.util.Date to java.sql.Date
答案 3 :(得分:2)
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);
答案 4 :(得分:1)
如果要将当前日期添加到数据库中,我将避免在Java中计算日期。如果客户端配置错误,时间错误,时区错误等,确定Java(客户端)端的“now”会导致数据库中出现不一致的情况。相反,日期可以在服务器端设置为方式如下:
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进行修复。
答案 5 :(得分:-1)
不确定,但我认为您正在寻找的是从String创建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对象上面的函数将打印出一个长值:
1375934400000