SQL查询中的java.lang.NullPointerException

时间:2012-08-10 09:10:57

标签: java sql oracle11g

我有SQL查询,它将数据插入Oracle行。我在运行声明时得到了NPE。

public int saveData(int result) throws SQLException, java.text.ParseException, NoSuchAlgorithmException {

    String SqlStatement = null;

    if (ds == null) {
        throw new SQLException();
    }

    Connection conn = ds.getConnection();
    if (conn == null) {
        throw new SQLException();
    }

    PreparedStatement ps = null;

    /*

    CREATE TABLE USERS(
        USERID INTEGER NOT NULL,
        GROUPID INTEGER,
        SPECIALNUMBER VARCHAR2(60 ),
        USERNAME VARCHAR2(50 ),
        PASSWD VARCHAR2(50 ),
        DATETOCHANGEPASSWD DATE,
        ADDRESS VARCHAR2(60 ),
        STATEREGION VARCHAR2(50 ),
        COUNTRY VARCHAR2(50 ),
        USERSTATUS VARCHAR2(30 ),
        TELEPHONE VARCHAR2(50 ),
        DATEUSERADDED DATE,
        USEREXPIREDATE DATE,
        DATEUSERLOCKED CHAR(20 ),
        CITY VARCHAR2(50 ),
        EMAIL VARCHAR2(50 ),
        DESCRIPTION CLOB
    )
   */

    try {
        conn.setAutoCommit(false);
        boolean committed = false;
        try {           
            String getTimeStampTemplateSQL = "(select (select settingvalue from globalsettings where settingname = 'DateFormat') || ' ' ||"
                                             + "(select settingvalue from globalsettings where settingname = 'TimeFormat') from dual)";

            /* insert into Oracle the default system(Linux) time */
            SqlStatement = "INSERT INTO USERS VALUES (?, ?, ?, ?, ?, to_timestamp(?, " 
                    + getTimeStampTemplateSQL + "), ?, ?, ?, ?, ?, SYSTIMESTAMP, to_timestamp(?, " + getTimeStampTemplateSQL +
                    "), ?, ?, ?, ?)";

            ps = conn.prepareStatement(SqlStatement);

            ps.setString(1, formMap.get("USERID"));
            ps.setString(2, formMap.get("GROUPID"));
            ps.setString(3, formMap.get("SPECIALNUMBER"));
            ps.setString(4, formMap.get("USERNAME"));
            ps.setString(5, passwdConvert(formMap.get("PASSWD")));
            ps.setString(6, formMap.get("DATETOCHANGEPASSWD").trim().length() == 0 ? null : formMap.get("DATETOCHANGEPASSWD").trim() + " " + formMap.get("HOURTOCHANGEPASSWD").trim());
            ps.setString(7, formMap.get("ADDRESS"));
            ps.setString(8, formMap.get("STATEREGION"));
            ps.setString(9, formMap.get("COUNTRY"));
            ps.setString(10, formMap.get("USERSTATUS"));

            // If the user set Account Status to Blocked insert SYSTIMESTAMP into DATEUSERLOCKED
            if ((formMap.get("USERSTATUS")!=null) && (formMap.get("USERSTATUS")).equals("Blocked")){
                formMap.put("DATEUSERLOCKED", "SYSTIMESTAMP");
            }               

            ps.setString(11, formMap.get("TELEPHONE"));
            ps.setString(12, formMap.get("USEREXPIREDATE").trim().length() == 0 ? null : formMap.get("USEREXPIREDATE").trim() + " " + formMap.get("USEREXPIREHOUR").trim());

            //ps.setString(13, formMap.get("DATEUSERLOCKED").trim().length() == 0 ? null : formMap.get("DATEUSERLOCKED"));

            ps.setString(13, ((formMap.get("DATEUSERLOCKED")==null) || ((formMap.get("DATEUSERLOCKED")!=null) && (formMap.get("DATEUSERLOCKED").trim().length()==0)))? null : formMap.get("DATEUSERLOCKED"));

            ps.setString(14, formMap.get("CITY"));
            ps.setString(15, formMap.get("EMAIL"));
            ps.setString(16, formMap.get("DESCRIPTION"));


            ps.executeUpdate();

            conn.commit();
            committed = true;
        }
        finally 
        {
            if (!committed) {
                conn.rollback();
            }
        }
    } finally {
        /* Release the resources */
        ps.close();
        conn.close();
    }
    // For JGrown message
    FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage("Successful", "User " + formMap.get("USERID") + " is created!"));

    return result;
}

我收到此错误:

javax.faces.FacesException: #{AddAccountController.saveData(1)}: java.sql.SQLDataException: ORA-01858: a non-numeric character was found where a numeric was expected

    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
    at javax.faces.component.UICommand.broadcast(UICommand.java:315)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1550)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655)
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:161)
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:331)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$AdapterCallable.call(ContainerMapper.java:317)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:195)
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:860)
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:757)
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1056)
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:229)
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
    at java.lang.Thread.run(Thread.java:722)
Caused by: javax.faces.el.EvaluationException: java.sql.SQLDataException: ORA-01858: a non-numeric character was found where a numeric was expected

    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102)
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
    ... 31 more
Caused by: java.sql.SQLDataException: ORA-01858: a non-numeric character was found where a numeric was expected

    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445)
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879)
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450)
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
    at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531)
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207)
    at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1044)
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1329)
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3584)
    at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3665)
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1352)
    at com.sun.gjc.spi.base.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:125)
    at com.DX_57.AC_57.AddAccount.saveData(AddAccount.java:207)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at javax.el.BeanELResolver.invokeMethod(BeanELResolver.java:779)
    at javax.el.BeanELResolver.invoke(BeanELResolver.java:528)
    at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:257)
    at com.sun.el.parser.AstValue.invoke(AstValue.java:248)
    at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:302)
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
    ... 32 more
|#]

你能帮我解决一下这个问题吗?也许准备好的陈述的顺序不正确?

P.S问题在于:

ps.setString(13, formMap.get("DATEUSERLOCKED").trim().length() == 0 ? null : formMap.get("DATEUSERLOCKED"));

4 个答案:

答案 0 :(得分:2)

(作为一般规则),您可以重写以下行以使其更安全:

if ((formMap.get("USERSTATUS")).equals("Blocked")) {

假设formMap != null,最好写:

if ("Blocked".equals(formMap.get("USERSTATUS"))) {

在这种情况下,即使formMap不包含密钥USERSTATUS,您也是安全的。

答案 1 :(得分:2)

抛出异常
AddAccount.java:221

如果你无法直接弄清楚这一行的作用(如果你能从这个文件中发布这段代码会很好)那么调试程序应该是找到错误的第一步(事实上 - - 是一般规则)。

您发布的代码的一般注释(也可能是问题的根本原因)。只要您执行formMap.get("<key>"),就无法确定formMap会为此not-null返回<key>个对象。您只是将从此映射返回的值直接分配给预准备语句的情况可能没有问题,但是当您将调用级联到该返回对象的其他方法时(如equalstrim)可能会导致如果对象为NPE,则null iff

因此,请考虑更改以下呼叫:

if ((formMap.get("USERSTATUS")).equals("Blocked")){
...
}

类似于:

if ((formMap.get("USERSTATUS")!=null) && (formMap.get("USERSTATUS")).equals("Blocked")){
...
}

if ("Blocked".equals(formMap.get("USERSTATUS"))){
...
}

以及您在地图上生成的项目上调用trimlength的地方

修改

使用三元运算符(?:)的情况对于null进行检查有点复杂:如果项目的长度为0,则需要指定null,因此这会导致故障遵循以下逻辑:

  

如果从formMap返回的对象为null或(如果对象返回   from formMap是非NULL并且它的长度为零)否则返回NULL   返回对象本身

因此,这会导致以下检查:

((formMap.get("DATEUSERLOCKED")==null) || ((formMap.get("DATEUSERLOCKED")!=null) && (formMap.get("DATEUSERLOCKED").trim().length()==0)))? null : formMap.get("DATEUSERLOCKED"));

答案 2 :(得分:1)

我能看到的NPE的唯一机会就是当你做

formMap.get(...).trim().length() ...
passwdConvert(formMap.get("PASSWD"))

您是否尝试过调试?

我在我的项目中应用的一般规则是:每行一个语句 - 这样StackTraces中的行符号更有帮助。

答案 3 :(得分:1)

尝试像这样添加null

ps.setString(13, formMap.get("DATEUSERLOCKED").trim().length() == 0 ? 'null' : formMap.get("DATEUSERLOCKED"));