java.sql.SQLDataException:ORA-01858:在更新日期时应为数字的位置发现了一个非数字字符



下面是我在Java DAO中的sql语句。当我试图更新入住和退房日期时,我收到了一个错误,说

java.sql.SQLDataException:ORA-01858:非数字字符在应为数字的位置找到。

是否需要使用simpledateformat将签入和签出从字符串转换为日期?如果是,如何在sql语句中插入。

HTML

<form>
<input type="date" id="checkin" class="form-control" >
<input type="date" id="checkout" class="form-control" >
</form

SQL

CREATE TABLE "HOMESTAY"."BOOKING" 
( "BOOKINGNUM" NUMBER(*,0) NOT NULL ENABLE, 
"CHECKIN" DATE, 
"CHECKOUT" DATE, 
"NUMOFDAYS" NUMBER(*,0), 
"TOTALCHARGES" FLOAT(10), 
"BFAST" VARCHAR2(10 BYTE), 
"CUSTIC" VARCHAR2(12 BYTE), 
"ACCID" NUMBER, 
CONSTRAINT "BOOKING_PK" PRIMARY KEY ("BOOKINGNUM")

Java

public void updateBooking(BookingBean bean) {

int bookingnum = bean.getBookingnum();
String checkin = bean.getCheckin();
String checkout = bean.getCheckout();
int numofdays = bean.getNumofdays();
float totalcharges = bean.getTotalcharges();
String bfast = bean.getBfast();
String custic = bean.getCustic();
int accid = bean.getAccid();

try {
currentCon = ConnectionManager.getConnection();
ps=currentCon.prepareStatement("UPDATE booking SET (checkin , checkout, 
numofdays, totalcharges, bfast, custic,accid)values(?,?,?,?,?,?,?)");

String s = checkin;
Date d = new SimpleDateFormat("yyyy-MM-dd").parse(s);       
String s1 = checkout;
Date d1 = new SimpleDateFormat("yyyy-MM-dd").parse(s1);
ps.setDate(1, new java.sql.Date(d.getTime()));
ps.setDate(2, new java.sql.Date(d1.getTime()));
ps.setInt(3,numofdays);
ps.setFloat(4,totalcharges);
ps.setString(5, bfast);
ps.setString(6,custic);
ps.setInt(7,accid);
ps.executeUpdate();
}
catch (Exception ex) {
System.out.println("failed: An Exception has occurred! " + ex);
}
finally {
if (ps != null) {
try {
ps.close();
} catch (Exception e) {
}
ps = null;
}
if (currentCon != null) {
try {
currentCon.close();
} catch (Exception e) {
}
currentCon = null;
}
}    
}

之所以发生这种情况,是因为您试图将Strings传递到update语句,但它需要字段checkincheckout上的Date类型。

对于update语句,应该尝试使用PreparedStatement传递参数。它更容易阅读和维护这里有一个网站,有一些有用的例子。

现在,对于您的Strings,您可以做两件事:

第一种是将这些BookingBean属性更改为Date类型。

第二种选择是继续使用您的Strings,并将它们作为日期传递给PreparedStatement,如下例所示:

try {
currentCon = ConnectionManager.getConnection();
PreparedStatement stmt = currentCon.prepareStatement(searchQuery);
stmt.setDate(1, java.sql.Date.valueOf("2018-11-08"));
stmt.executeUpdate(searchQuery);
} catch (SQLException e) {
e.printStackTrace();
}

Ps。对于第一个选项,只需将日期属性传递给stmt.setDate

此外,以下是如何正确写入update命令的示例。

tl;dr

永远不要使用糟糕的老式日期时间类,如java.sql.Datejava.util.DateCalendar和`SimpleDateFormat。使用它们的替代品,即现代的java.time类。

myPreparedStatement.setObject( … , LocalDate.parse( "2018-11-08" ) )

…和…

LocalDate localDate = myResultSet.getObject( … , LocalDate.class ) ;

java.time

Krum的Answer是正确的,只是它使用了可怕的java.sql.Date类,该类在几年前由于JSR310的采用而过时了。正如该答案中所建议的,您应该使用智能对象而不是哑字符串来与数据库交换日期-时间值。

让我们调整一下Krum提供的代码。两个变化:(a(用现代类替换遗留类,以及(b(在输入错误的情况下分别解析输入字符串。

java.time.LocalDate localDate = null ;             // Use the modern `java.time.LocalDate` class that years ago supplanted the terribly-designed `java.sql.Date` class.
try {
localDate = LocalDate.parse( "2018-11-08" ) ;  // The java.time classes by default know how to parse strings in standard ISO 8601 format such as seen here.
} catch ( DateTimeParseException e ) {
… // Deal with invalid input string.
}
try {
currentCon = ConnectionManager.getConnection() ;
PreparedStatement stmt = currentCon.prepareStatement( searchQuery ) ;
stmt.setObject(1, localDate ) ;                // As of JDBC 4.2, we can directly exchange java.time objects with a database via the `setObject` and `getObject` methods.
stmt.executeUpdate( searchQuery ) ;
} catch (SQLException e) {
e.printStackTrace() ;
}

以及用于检索。

LocalDate localDate = myResultSet.getObject( … , LocalDate.class ) ;

关于java.time

java.time框架构建在Java8及更高版本中。这些类取代了诸如java.util.DateCalendar和&SimpleDateFormat

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

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

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

从哪里获得java.time类?

  • Java SE 8Java SE 9Java SE 10爪哇SE 11及更高版本-标准Java API的一部分,带有捆绑实现。
    • Java9添加了一些小功能和修复程序
  • Java SE 6Java SE 7
    • 大多数Java.time功能都是向后移植到Java 6&7英寸ThreeTen背包
  • Android
    • java.time类的Android捆绑包的后续版本
    • 对于早期的Android(<26(,ThreeTenABP项目适用于ThreeTen Backport(如上所述(。请参阅如何使用ThreeTenABP…

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

相关内容

最新更新