【问题标题】:Convert String into TIMESTAMP for insert into Database oracle from servlet java将字符串转换为 TIMESTAMP 以便从 servlet java 插入数据库 oracle
【发布时间】:2019-07-03 00:32:28
【问题描述】:

我正在尝试从 servlet 将日期插入 Oracle 数据库中的 TIMESTAMP 字段。 但是当我插入时,我得到一个错误:“ORA-01843:月份无效”

我在日期所在的表格中看到的日期类型是:05-FEB-19 09.36.10.000000000 AM 我在表创建为 TIMESTAMP 类型时声明了它。

在 JSP 文件中我有这两种输入类型:

<label>Data
<input type="date" name="date" value="13-AUG-2019" required>
</label>
<label>Time
<input type="time" name="time" value="11:00:00 AM" required>
</label>

在 Servlet Java 中我有这个:

    String data= request.getParameter("date");
    String time= request.getParameter("time");
    String paramData = data.replaceAll("\n", "");
    String paramTime = time.replaceAll("\n", "");
    String dataTime = paramData + " " + paramTime;

    try{
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection connCf = DriverManager.getConnection(url, user, pass);

        PreparedStatement pstmtCf=connCf.prepareStatement("insert into screening_tab (film_oid, room_oid, data_hour) values((select ref(fi) from film_tab fi where fi.title=?), (select ref(ro) from room_tab ro where ro.code=?), ?)");

        pstmtCf.setString(1, paramFilm);
        pstmtCf.setString(2, paramRoom);
        String paramDataTime= paramData + " " + paramTime;
        pstmtCf.setString(3, paramDataTime);

        Boolean result= pstmtCf.execute();

我该如何解决这个问题?

我在 Oracle 10 中尝试过这个解决方案,给定来自 servlet 的字符串返回时间戳,但问题是一样的:

create or replace procedure Sdata (datatime VarCHAR2) is
date_ho TIMESTAMP;
begin
SELECT TO_TIMESTAMP (datatime, 'DD-MON-RR HH.MI.SSXFF AM') into date_ho  FROM DUAL;
dbms_output.enable;
dbms_output.put_line(date_ho);
end sdata;

在各种尝试和试验之间,我无法解释如果我在 Oracle SQL Developer 中执行这样的操作,一切正常!:

insert into screening_tab (film_oid, room_oid, data_hour) values((select ref(fi) from film_tab fi where fi.title='FilmNumero601'), (select ref(ro) from room_tab ro where ro.code=301), '14-DEC-19 07.00.00.00 PM' );

当我从 servlet 运行完全相同的查询时,我总是在无效的月份日期得到错误

我也尝试过这个解决方案:我创建了一个新的 Servlet 和 JSP 文件,其中数据输入是:

<h4>Select Data: </h4><br></br>
                                <input type="datetime-local"  name="date" arequired placeholder="Date">
                                <br></br>
                                <input type="reset"  value="Resetta la form"></input>
                                <input type="submit" value="Invia"></input>

在相应的 servlet 中我有这个:

PreparedStatement pstmtCf=connCf.prepareStatement("insert into screening_tab (film_oid, room_oid, data_hour) values((select ref(fi) from film_tab fi where fi.title=?), (select ref(ro) from room_tab ro where ro.code=?), ?)");



            pstmtCf.setString(1, film);
            pstmtCf.setString(2, room);
            String date= getCorrectFormat(request.getParameter("date")+":00");
            pstmtCf.setString(3, date );


            pstmtCf.execute();



            pstmtCf.close();
            connCf.close();

getCorrectFormat() 在哪里:

public static String getCorrectFormat(String date){
        String out="";
        out += (date.substring(8,10))+ "-";
        switch(date.substring(5,7)){
        case "01":
            out += "JAN-";
            break;
        case "02":
            out += "FEB-";
            break;
        case "03":
            out += "MAR-";
            break;
        case "04":
            out += "APR-";
            break;
        case "05":
            out += "MAY-";
            break;
        case "06":
            out += "JUN-";
            break;
        case "07":
            out += "JUL-";
            break;
        case "08":
            out += "AUG-";
            break;  
        case "09":
            out += "SEP-";
            break;
        case "10":
            out += "OCT-";
            break;
        case "11":
            out += "NOV-";
            break;
        case "12":
            out += "DEC-";
            break;
        }
        out += (date.substring(0,4))+ " ";
        int hour =Integer.parseInt(date.substring(11,13))%12;
        if(hour == 0)
            out += String.valueOf(12);
        else
            out += String.valueOf(hour);
        out += (date.substring(13));
        if(Integer.parseInt(date.substring(11,13))<12)
            out += " AM";
        else
            out += " PM";
        return out;
    }

错误总是一样的:“ORA-01843:not a valid month”

【问题讨论】:

  • 只是为了挑剔,我认为您需要将字符串 convert 从字符串转换为时间戳,而不是 cast。 (虽然现在我正在寻找一个定义来支持这一点,但我找不到一个。但在我看来,转换意味着比铸造更彻底的重组。)
  • Marco,您的回答对您有帮助吗?如果您仍然缺少某些东西,请随时在 cmets 中跟进(或提出新问题)。如果您认为您的问题已得到解答,请接受最有帮助的答案。 What should I do when someone answers my question?

标签: java oracle jsp jdbc timestamp


【解决方案1】:

使用对象,而不是字符串。

从 JDBC 4.2 开始,我们可以通过 PreparedStatement::setObjectResultSet::getObject 方法直接与数据库交换 java.time 对象。在准备好的语句中,使用? 占位符,如Oracle Tutorial 所示。

LocalDate ld = LocalDate.of( 2019 , 8 , 13 ) ;
myPreparedStatement.setObject( … , ld ) ;

还有……

LocalTime lt = LocalTime.of( 11 , 0 ) ;
myPreparedStatement.setObject( … , lt ) ;

检索。

LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
LocalDate lt = myResultSet.getObject( … , LocalTime.class ) ;

关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

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

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

从哪里获得 java.time 类?

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

【讨论】:

  • 我遵循所写的内容,它会给我一个不适合我的 Oracle 数据库的日期值。我尝试了不同的解决方案,例如:1)我创建了一个函数,该函数从 servlet 返回一个时间戳:创建或替换过程 Sdata(datatime VarCHAR2)是 date_ho TIMESTAMP;开始 SELECT TO_TIMESTAMP (datatime, 'DD-MON-RR HH.MI.SSXFF AM') into date_ho FROM DUAL; dbms_output.enable; dbms_output.put_line(date_ho);结束数据;
  • @Marco 正如我的第一个标题所说,使用对象,而不是字符串。您的问题和评论中发生了太多事情,以至于我看不到您的实际目标/问题。我建议您搜索 Stack Overflow 以进一步了解 java.time 对象,以及如何调用 PreparedStatement::setObjectResultSet::getObject。这一切已经在 Stack Overflow 上被多次介绍过。目前你似乎工作太努力了,而且方向都错了,努力处理字符串操作,而不是学习使用行业领先的日期时间框架 (java.time)。
【解决方案2】:

您传入了一个字符串/varchar2,并且由于您的日期/时间格式与您的 Oracle 默认日期/时间格式不匹配,隐式转换为时间戳失败。

最简单的选择是传递一个格式字符串,以便 Oracle 知道如何进行转换。您可以使用to_timestamp(?, 'DD-MON-YYYY HH:MI:SS AM')

,而不是传递? 作为时间戳

如果您已经有 Java 时间戳,我想您应该使用 setTimestamp() - see this question

【讨论】:

  • @Marco 如果在问题中报告您尝试了什么以及失败的原因,我们通常更容易为您提供帮助。谢谢。
  • 我已经用我已经实施的解决方案更新了我的问题,但也出现了同样的问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-25
  • 2018-01-25
  • 1970-01-01
  • 2019-02-13
  • 2021-11-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多