SQL查询中的java.lang.NullPointerException

SQL查询中的java.lang.NullPointerException,java,sql,oracle11g,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(); } Conn

我有一个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
|#]
你能帮我解决这个问题吗?也许准备的陈述顺序不正确

问题在于:

ps.setString(13, formMap.get("DATEUSERLOCKED").trim().length() == 0 ? null : formMap.get("DATEUSERLOCKED"));
(作为一般规则),为了更安全,您可以重写以下行:

if ((formMap.get("USERSTATUS")).equals("Blocked")) {
假设
formMap!=空
,最好写:

if ("Blocked".equals(formMap.get("USERSTATUS"))) {
在这种情况下,即使formMap不包含键
USERSTATUS

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

if ((formMap.get("USERSTATUS")).equals("Blocked")) {
假设
formMap!=空
,最好写:

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

在这种情况下,即使formMap不包含键
USERSTATUS

,您也是安全的。我看到NPE的唯一机会就是当您这样做时

formMap.get(...).trim().length() ...
passwdConvert(formMap.get("PASSWD"))
你试过调试了吗


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

我能看到NPE的唯一机会就是当你这样做的时候

formMap.get(...).trim().length() ...
passwdConvert(formMap.get("PASSWD"))
你试过调试了吗


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

AddAccount.java:221
如果您不能直接理解这行代码的作用(如果您可以发布此文件的代码摘录,那就太好了),那么调试程序应该是查找错误的第一步(事实上,这是一条一般规则)

对您发布的代码的一般性评论(这也可能是问题的根本原因)。无论何时执行
formMap.get(“”)
操作,都不能确定
formMap
将为此
返回一个
非空的
对象。如果您只是将此映射返回的值直接分配给准备好的语句,可能不会有问题,但是当您将调用级联到该返回对象的其他方法时(例如
equals
trim
),如果对象为
null
,则可能会导致
NPE
iff

请考虑更改调用:

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

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

在地图结果项上调用
trim
length
的位置

编辑

三元运算符(
?:
)的情况在检查
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"));

异常被抛出

AddAccount.java:221
如果您不能直接理解这行代码的作用(如果您可以发布此文件的代码摘录,那就太好了),那么调试程序应该是查找错误的第一步(事实上,这是一条一般规则)

对您发布的代码的一般性评论(这也可能是问题的根本原因)。无论何时执行
formMap.get(“”)
操作,都不能确定
formMap
将为此
返回一个
非空的
对象。如果您只是将此映射返回的值直接分配给准备好的语句,可能不会有问题,但是当您将调用级联到该返回对象的其他方法时(例如
equals
trim
),如果对象为
null
,则可能会导致
NPE
iff

请考虑更改调用:

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

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

在地图结果项上调用
trim
length
的位置

编辑

三元运算符(
?:
)的情况在检查
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"));

尝试按如下方式添加
null

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

尝试按如下方式添加
null

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

发布你的类完整代码(如果代码较少)。发布你的类完整代码(如果代码较少)。你的一般规则牺牲了一些可读性(这需要一直存在),以便在查找问题(希望最多只发生一次)时更轻松。为什么不在知道有问题时才更改代码?…我的另一条规则是保持方法简短,并将具有多个调用的方法重构为名称更支持可读性的方法,而不是将多个方法放在同一行上(对我来说,这似乎并不支持可读性,但只支持一个最小的LOC度量)。您的一般规则牺牲了一些可读性(需要始终存在),以便在查找问题(希望最多只发生一次)时获得一些方便。为什么不在知道有问题时才更改代码?…我的另一条规则是保持方法简短,并将具有多个调用的方法重构为名称更支持可读性的方法,而不是将多个方法放在同一行上(对我来说,这似乎不支持可读性,但只支持最小LOC度量)。我测试了你的代码,但它再次不起作用。我更新了post代码。但现在你得到了一个不同的错误;)。您似乎传递了一个非数字的值,而该值应该是数字。请检查表中列的数据类型,并调试传递到prepared语句的输入。我注意到了更多事项。表有17列,insert语句处理16个。