【问题标题】:Oracle chokes on date format sent from Kendo DataSourceOracle 阻塞了从 Kendo DataSource 发送的日期格式
【发布时间】:2014-07-16 20:54:15
【问题描述】:

我有一个 DataSource,它将 Odata 传递给 Teiid,然后传递给 Oracle。但是,当我尝试从 Kendo DataSource 传递一个日期时,Oracle 感到窒息。我认为这是因为 Oracle 无法识别其发送格式的日期字符串 - 例如,2014-07-01T05:00:00.000Z - 是有效的。这是我得到的错误:

avax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.4.1.v20121003-ad44345): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.teiid.jdbc.TeiidSQLException: TEIID30504 JTRAC_DEV_ENV: 1843 TEIID11013:TEIID11004 Error executing statement(s): [Prepared Values: ['2014-07-01T05:00:00.000Z', 700281, 700280] SQL: UPDATE "JTRAC"."MAPPED_HISTORY" SET "TIME_STAMP" = ? WHERE "JTRAC"."MAPPED_HISTORY"."HISTORY_ID" = ? AND "JTRAC"."MAPPED_HISTORY"."ITEM_ID" = ?]
Error Code: 1843
Call: UPDATE "JTRAC.MAPPED_HISTORY" SET "TIME_STAMP" = ? WHERE ((("HISTORY_ID" = ?) AND ("ITEM_ID" = ?)) AND ("TEIID_MULTI_DATA_SOURCE_COLUMN" = ?))
bind => [2014-07-01T05:00:00.000Z, 700281, 700280, JTRAC_DEV_ENV]

如何将时间戳更改为可以使用的内容?我已经尝试使用 parameterMap (似乎还没有在那个阶段转换它 - 仍然是相当正常的时间格式),requestStart(我似乎无法访问数据以篡改它)和解析(isn' t 以我期望的方式工作)。作为记录,另一端有一个 INSTEAD OF Oracle 触发器,因为最终我正在更新一个视图。想法?

这是我正在使用的触发器:

create or replace 
trigger update_mapped_history
  INSTEAD OF UPDATE ON mapped_history
  FOR EACH ROW
DECLARE
  new_status_id number;
  new_assigned_to number;
  new_logged_by number;
  new_timestamp timestamp;
  cmmd VARCHAR2(100);
BEGIN
  cmmd:='alter session set NLS_TIMESTAMP_FORMAT=''YYYY-MM-DD"T"HH:MI:SS.FF"Z"''';
  EXECUTE IMMEDIATE cmmd;
  SELECT status_id INTO new_status_id FROM status_int_mapping WHERE status_label=:NEW.status AND space_id = (select i.space_id from items i where i.id = :OLD.item_id);
  SELECT id INTO new_assigned_to FROM users WHERE login_name = :NEW.assigned_to;
  SELECT id INTO new_logged_by FROM users WHERE login_name = :NEW.logged_by;
  select FROM_TZ(TO_TIMESTAMP(:NEW.time_stamp, 'YYYY-MM-DD"T"HH:MI:SS.FF"Z"'),'UTC') at time zone 'US/Central' into new_timestamp from dual;
  UPDATE history SET
    logged_by = new_logged_by, 
    status = new_status_id,
    assigned_to = new_assigned_to,
    jt_comment = :NEW.jt_comment,
    time_stamp = new_timestamp
  WHERE id=:OLD.history_id;
END;

这是我的所有荣耀的代码。

historyDataSource = new kendo.data.DataSource({
        //autoSync: true,
        type: "odata",
        serverFiltering: true,
        serverPaging: true,
        serverSorting: true,
        pageSize: 10,
        transport: {
            read: {
                url: baseUrl + "MAPPED_HISTORY",
                type: "GET",
                headers: {
                    Authorization: authorizationStr64
                },
                dataType: "json"
            },
            update: {
                url: function(options){
                    return kendo.format(baseUrl + "MAPPED_HISTORY"+"({0})", options.HISTORY_ID);
                },
                type: "PUT",
                headers: {
                    Authorization: authorizationStr64
                },
                dataType: "json",
                contentType: "application/json"
            },
            create: {
                url: baseUrl + "MAPPED_HISTORY",
                type: "POST",
                headers: {
                    Authorization: authorizationStr64
                },
                dataType: "json"
            },
            destroy: {
                //url: "http://amr-dsiprod05:8080/odata/SDA/TEIID_TEST",
                url: function(options){
                    return kendo.format(baseUrl + "MAPPED_HISTORY"+"({0})", options.HISTORY_ID);
                },
                type: "DELETE",
                headers: {
                    Authorization: authorizationStr64
                },
                dataType: "json"
            },
            parameterMap: function(data,type){
                if(type=='update'){
                    debugger;
                }
                return data;
            }
        },
        // Enable server filtering so we don't have to download the whole history data set
        serverFiltering: true,
        filter: { logic: "and", filters: [ { field: "HISTORY_ID", operator: "equals", value: historyId } ] },

        "schema": {
            "model": {
                "id": "HISTORY_ID",
                "fields": {
                    /*"HISTORY_ID": {
                        "editable": true,
                        "nullable": false
                    },
                    "ITEM_ID": {
                        "editable": true,
                        "nullable": true
                    },*/
                    "LOGGED_BY": {
                        "editable": false,
                        "nullable": true
                    },
                    "STATUS": {
                        "editable": false,
                        "nullable": false
                    },
                    "ASSIGNED_TO": {
                        "editable": false,
                        "nullable": true
                    },
                    "JT_COMMENT": {
                        "editable": true,
                        "nullable": true
                    },
                    "TIME_STAMP": {
                        "editable": true,
                        "nullable": false
                    }
                }
            },
            errors: "error"/*,
            parse:function (response) {
                $.each(response, function (idx, elem) {
                    if (elem.Date && typeof elem.Date === "string") {
                        elem.Date = kendo.parseDate(elem.Date, "yyyy-MM-ddTHH:mm:ss.fffZ");
                        console.log(elem.Date);
                        debugger;
                    }
                });
                return response;
            }*/
        },
        error: function(e){
            if(confirm("Could not update or display data! Show full error report?")){
                var myWindow = window.open("", "MsgWindow", "width=1000, height=800,resizable=yes, ");
                myWindow.document.write(e.xhr.responseText);
            }
            //console.log();
        },
        /*requestStart: function(e){
            if(e.type=='update'){
                debugger;
            }
        },
        requestEnd: function(e){
            if(e.type=='update'){
                debugger;
                for(var i=0; i<e.response.d.results.length; i++){  
                    var timeStamp = kendo.parseDate(e.response.d.results[i].time_stamp);
                    var utcTimeStamp = new Date(timeStamp.getTime() + timeStamp.getTimezoneOffset() * 60000);
                    e.response.d.results[i].OrderDate = utcTimeStamp;
                    alert(utcTimeStamp);
                }
                debugger;//alert('updating kendo!');
            }
        }*/
    });   
    historyDataSource.read();


    $("#" + divId).kendoGrid({
        "dataSource": historyDataSource,
        "autoBind": false,
        "pageable": true,
        "height": 350,
        "selectable": true,
        "editable": true,
        "toolbar": [/*"create",*/"save","cancel"],
        "columns": [
            //{ "field": "HISTORY_ID", "width":"100px" },
            //{ "field": "ITEM_ID", "width":"100px" },
            { "field": "LOGGED_BY", "width":"160px", editor: usersDropDownEditor, template: "#=LOGGED_BY#"  },
            { "field": "STATUS", "width":"200px" , editor: statusDropDownEditor, template: "#=STATUS#"  },
            { "field": "ASSIGNED_TO", "width":"160px", editor: usersDropDownEditor, template: "#=ASSIGNED_TO#"  },
            { "field": "JT_COMMENT"},
            { "field": "TIME_STAMP", "width":"200px", format: "{0:MM/dd/yyyy hh:mm tt}", editor: dateTimeEditor }//,
            //{ "command": "destroy" }
        ]
    });

    function dateTimeEditor(container, options) {
        $('<input data-text-field="' + options.field + '" data-value-field="' + options.field + '" data-bind="value:' + options.field + '" data-format="' + options.format + '"/>')
                .appendTo(container)
                .kendoDateTimePicker({
                    interval: 05,
                    min: new Date(2011, 0, 1),
                    timeFormat: "HH:mm"
                    /*parseFormats: ["yyyy-MM-dd hh:mm:ss"]*/
                });
    }

    function statusDropDownEditor(container, options) {
        var statusInput = $('<input required data-text-field="STATUS_LABEL" data-value-field="STATUS_LABEL" data-bind="value:' + options.field + '"/>')
            .appendTo(container)
            .kendoDropDownList({
                autoBind: false,
                dataSource: {
                    type: "odata",
                    transport: {
                        read: {
                            url: baseUrl + "STATUS_INT_MAPPING",
                            type: "GET",
                            headers: {
                                Authorization: authorizationStr64
                            },
                            dataType: "json"
                        }
                    },
                    serverFiltering: true,
                    filter: { logic: "and", filters: [ {field: "SPACE_ID", operator: "equals", value: spaceId}]}
                }
            });
    }

    function usersDropDownEditor(container, options) {
        var usersInput= $('<input required data-text-field="LOGIN_NAME" data-value-field="LOGIN_NAME" data-bind="value:' + options.field + '"/>')
            .appendTo(container)
            .kendoDropDownList({
                autoBind: false,
                dataSource: {
                    type: "odata",
                    transport: {
                        read: {
                            url: baseUrl + "SPACE_LOGIN_NAMES",
                            type: "GET",
                            headers: {
                                Authorization: authorizationStr64
                            },
                            dataType: "json"
                        }
                    },
                    serverFiltering: true,
                    filter: { logic: "and", filters: [ {field: "SPACE_ID", operator: "equals", value: spaceId}]}
                }
            });
    }
});

【问题讨论】:

    标签: oracle kendo-ui kendo-grid odata kendo-datasource


    【解决方案1】:

    要么使用显式的TO_TIMESTAMP() 函数,要么在客户端设置NLS_TIMESTAMP_FORMAT。

    更多信息可以在这里找到:

    TO_TIMESTAMP() 函数 http://docs.oracle.com/cd/E16655_01/server.121/e17209/functions223.htm#SQLRF06142

    NLS_TIMESTAMP_FORMAT http://docs.oracle.com/cd/E16655_01/server.121/e17615/refrn10131.htm#REFRN10131

    【讨论】:

    • 我在写入视图的 INSTEAD OF Oracle 触发器中尝试了 TO_TIMESTAMP。唯一的问题是,当它看到预期的时间戳值不是时间戳时,我认为它退出了。如果再进一步,它会成功转换它!你认为 NLS_TIMESTAMP_FORMAT 会绕过它吗?
    • 嗯,这个想法是您应该始终明确地将字符串转换为时间戳,并使用指定的格式字符串。这样做的方法是 TO_TIMESTAMP() 函数。否则,Oracle 将使用 NLS_TIMESTAMP_FORMAT 中指定的格式字符串进行隐式转换。所以,是的,如果你放弃使用 TO_TIMESTAMP(),那么在 NLS_TIMESTAMP_FORMAT 中设置正确的格式字符串 应该 解决你的问题。试一试,让我知道它是否有效。
    • 是的,但问题是我通过 Odata 间接发送这些查询。如何配置 Kendo UI 以发送 TO_TIMESTAMP()?我已经在我的主要问题中包含了我正在使用的触发器。改变会话的东西不起作用,因为在 Oracle 认为它正在接收时间戳之前我无法运行它。我无法在每次用户登录时更改时间戳,因为它会干扰其他查询。
    • 抱歉,我对 Odata 或 Kendo UI 一无所知,所以我无能为力。使用数据库登录触发器设置 NLS_TIMESTAMP_FORMAT 怎么样?并且不用担心使用 TO_TIMESTAMP(),Oracle 会进行隐式转换并使用 NLS_TIMESTAMP_FORMAT 的值。
    • 我已经考虑过了,但这会干扰提交其他时间戳的用户的其他数据库操作。我想我可以为我的 Odata 东西创建一个数据库用户。
    猜你喜欢
    • 2014-10-06
    • 2014-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-24
    • 1970-01-01
    • 2013-09-22
    相关资源
    最近更新 更多