简体   繁体   中英

java.lang.NullPointerException in SQL query

I have SQL query which inserts data into Oracle row. I get NPE when I run the statement.

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;
}

I get this error:

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
|#]

Can you please help me to fix the problem? Maybe the order of the prepared statements is not correct?

PS the problem is here:

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

(As a general rule), You may rewrite the following line to be safer:

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

Supposing that formMap != null , it's better to write:

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

In this case you are safe even if formMap does not contain the key USERSTATUS .

The exception is thrown at

AddAccount.java:221

If you can't figure out directly what this line does (it would be nice if you could post this excerpt of code from this file) then debugging the program should be your first step of finding the error (this - in fact - is a general rule).

A general comment for your posted code (which might be the root cause of the problem as well). Whenever you do formMap.get("<key>") you can't say for sure the formMap will return a not-null object for this <key> . The case that you just assigning the values returned from this map directly to the prepared statement might not be problem, but when you cascading calls to other methods of that returned object (like equals or trim may lead to the NPE iff if the object is null ).

So consider changing calls like:

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

to something like:

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

or

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

and in the places you call trim and length on the resulting item from the map

EDIT

The cases you have with the ternary operator ( ?: ) are a little more complex for checking against null : You need to assign null if the length of the item is 0, so this breaks down to the following logic:

If the object returned from formMap is null OR (if the object returned from formMap is NOT NULL AND it has zero length) return NULL otherwise return the object itself

So this leads to the following check:

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

The only chances for an NPE I can see are when you do

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

Have you tried debugging yet?

General rule I apply on my projects is: a single statement per line - this way the line-nubers in StackTraces are way more helpful.

尝试像这样添加null

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM