使用CallableStatement设置NULL

时间:2013-09-18 11:30:15

标签: sql-server jdbc callable-statement

我正在使用JDBC与sql server 2008.我在表中有一个类型为“decimal(18,2)”的列。我想使用“CallableStatement”向此列插入一个空值。我该怎么做?

我试过了callstmt.setNull(14, java.sql.Types.DECIMAL);。但这不起作用。

HTTP状态404 - /NSBMHCGcom.microsoft.sqlserver.jdbc.SQLServerException:%20Error%20converting%20data%20type%20nvarchar%20to%20numeric./eHRMS_AR_M_display_SetupOTConditions

这是我得到的错误。

输入状态报告

消息/NSBMHCGcom.microsoft.sqlserver.jdbc.SQLServerException:%20Error%20converting%20data%20type%20nvarchar%20to%20numeric./eHRMS_AR_M_display_SetupOTConditions

说明请求的资源(/NSBMHCGcom.microsoft.sqlserver.jdbc.SQLServerException:%20Error%20converting%20data%20type%20nvarchar%20to%20numeric./eHRMS_AR_M_display_SetupOTConditions)不可用。

这是代码的一部分。

strSQL = "INSERT INTO " + m_schema_name + ".[AR_M_OTConditions] ([ConditionDescription],[StartHour],[EndHour]"
                        + " ,[Day],[IsActive],"
                        + "[EntDate],[EntUser],[ModDate],[ModUser],[Rate],[MinOT],[MaxOT],[EmpCategory],[EmpType],[Condition],[MinHour],[MaxHour],[Amount]) VALUES (?,?,?,?,?,getDate(),?,getDate(),?,?,?,?,?,?,?,?,?,?)";
                callstmt = conn.prepareCall(strSQL);
                callstmt.setString(1, m_con_methods.met_formdata(reqstr, "TXT_LEVELNAME"));
                callstmt.setString(2, m_con_methods.met_formdata(reqstr, "TXT_FROM"));
                callstmt.setString(3, m_con_methods.met_formdata(reqstr, "TXT_TO"));
                callstmt.setString(4, m_con_methods.met_formdata(reqstr, "TXT_FINYEAR"));
                callstmt.setBoolean(5, true);
                callstmt.setString(6, m_username);
                callstmt.setString(7, m_username);
                callstmt.setString(8, m_con_methods.met_formdata(reqstr, "TXT_RATE"));
                callstmt.setString(9, m_con_methods.met_formdata(reqstr, "TXT_MIN") );
                callstmt.setString(10, m_con_methods.met_formdata(reqstr, "TXT_MAX"));
                callstmt.setString(11, m_con_methods.met_formdata(reqstr, "TXT_CHARGABLE_STATUS"));
                callstmt.setString(12, m_con_methods.met_formdata(reqstr, "TXT_TYPE"));
                callstmt.setString(13, m_con_methods.met_formdata(reqstr, "TXT_CONDITIONS"));
                callstmt.setNull(14, java.sql.Types.DECIMAL);
                callstmt.setString(15, m_con_methods.met_formdata(reqstr, "TXT_MAX_HOUR"));
                callstmt.setString(16, m_con_methods.met_formdata(reqstr, "TXT_CONDITIONS_AMOUNT"));

=============================================== ================================================== ===

com.microsoft.sqlserver.jdbc.SQLServerException: Error converting data type nvarchar to numeric.
log4j:ERROR Could not find value for key log4j.appender.warn
log4j:ERROR Could not instantiate appender named "warn".
log4j:ERROR setFile(null,true) call failed.
java.io.FileNotFoundException: C:\Program Files\Apache Software Foundation\Apache Tomcat 6.0.18\logs\NSBM.log (The system cannot find the path specified)
    at java.io.FileOutputStream.openAppend(Native Method)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:192)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:116)
    at org.apache.log4j.FileAppender.setFile(FileAppender.java:290)
    at org.apache.log4j.FileAppender.activateOptions(FileAppender.java:164)
    at org.apache.log4j.config.PropertySetter.activate(PropertySetter.java:257)
    at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:133)
    at org.apache.log4j.config.PropertySetter.setProperties(PropertySetter.java:97)
    at org.apache.log4j.PropertyConfigurator.parseAppender(PropertyConfigurator.java:689)
    at org.apache.log4j.PropertyConfigurator.parseCategory(PropertyConfigurator.java:647)
    at org.apache.log4j.PropertyConfigurator.configureRootCategory(PropertyConfigurator.java:544)
    at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:440)
    at org.apache.log4j.PropertyConfigurator.doConfigure(PropertyConfigurator.java:476)
    at org.apache.log4j.helpers.OptionConverter.selectAndConfigure(OptionConverter.java:471)
    at org.apache.log4j.LogManager.<clinit>(LogManager.java:125)
    at org.apache.log4j.Logger.getLogger(Logger.java:105)
    at pwc.ehrms.common.CommonConnections.LogSystemErrors(CommonConnections.java:633)
    at pwc.ehrms.master.eHRMS_AR_M_save_SetupOTConditions.service(eHRMS_AR_M_save_SetupOTConditions.java:165)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)

=============================================== ================================================== ===

1 个答案:

答案 0 :(得分:0)

假设您有一个包含输入类型对象和输出类型对象的包

CustomInputType customInputType = transform(customView);
final String query = "{?=call SCHEMA_DBA.PRJ_PKG_CUSTOM.FUNC_CUSTOM_X(?)}";
fdb.setUpCallable(query);
final Map<String, Class<?>> typeMap = fdb.getConnection().getTypeMap();
typeMap.put("SCHEMA_DBA.TY_CUSTOM_INPUT", Class.forName("com.myproject.view.CustomInputType"));
typeMap.put("SCHEMA_DBA.FI_TY_CUSTOM_OUTPUT", Class.forName("com.myproject.view.CustomOutputType"));
typeMap.put("TY_CUSTOM_INPUT", Class.forName("com.myproject.view.CustomInputType"));
typeMap.put("FI_TY_CUSTOM_OUTPUT", Class.forName("com.myproject.view.CustomOutputType"));
fdb.getCallableStatement().registerOutParameter(1, Types.STRUCT, "SCHEMA_DBA.FI_TY_CUSTOM_OUTPUT");
fdb.getCallableStatement().setObject(2, customInputType);
fdb.executeCallable();
CustomOutputType customOutputType = (CustomOutputType) callableStatement.getObject(1);
CustomOutput customOutput = valorizzaCaricaLineeDiFido(customOutputType);

在 CustomInputType 中你必须有

import java.sql.Date;
import java.sql.SQLData;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;

public class CustomInputType implements SQLData {

    String sql_type = "SCHEMA_DBA.TY_CUSTOM_INPUT";

    String inputStringX;
    Long inputLongY;
    Date inputDataZ;
    Double inputDoubleW;

    public String getInputStringX() {
        return inputStringX;
    }

    public void setInputStringX(String inputStringX) {
        this.inputStringX = inputStringX;
    }

    public Long getInputLongY() {
        return inputLongY;
    }

    public void setInputLongY(Long inputLongY) {
        this.inputLongY = inputLongY;
    }

    public Date getInputDataZ() {
        return inputDataZ;
    }

    public void setInputDataZ(Date inputDataZ) {
        this.inputDataZ = inputDataZ;
    }

    public Double getInputDoubleW() {
        return inputDoubleW;
    }

    public void setInputDoubleW(Double inputDoubleW) {
        this.inputDoubleW = inputDoubleW;
    }

    // -- sqlType -- v
    @Override
    public String getSQLTypeName() throws SQLException {
        return sql_type;
    }

    public String getSqlType() {
        return sql_type;
    }
    // -- sqlType -- ^

    // -- read/write Data utility-- v
    public Long readDataLong(SQLInput stream) throws SQLException {
        Long dataLong = stream.readLong();
        if (stream.wasNull()) {
            dataLong = null;
        }
        return dataLong;
    }

    public Double readDataDouble(SQLInput stream) throws SQLException {
        Double dataDouble = stream.readDouble();
        if (stream.wasNull()) {
            dataDouble = null;
        }
        return dataDouble;
    }

    public void writeDataLong(SQLOutput stream, Long dataLong) throws SQLException {
        if (dataLong != null) {
            stream.writeLong(dataLong);
        } else {
            stream.writeObject(null);
        }
    }

    public void writeDataDouble(SQLOutput stream, Double dataDouble) throws SQLException {
        if (dataDouble != null) {
            stream.writeDouble(dataDouble);
        } else {
            stream.writeObject(null);
        }
    }
    // -- read/write Data utility-- ^

    @Override
    public void readSQL(SQLInput stream, String typeName) throws SQLException {
        this.sql_type = typeName;
        this.inputStringX = stream.readString();
        this.inputLongY = readDataLong(stream);
        this.inputDataZ = stream.readDate();
        this.inputDoubleW = readDataDouble(stream);
    }

    @Override
    public void writeSQL(SQLOutput stream) throws SQLException {
        stream.writeString(this.inputStringX);
        writeDataLong(stream, this.inputLongY);
        stream.writeDate(this.inputDataZ);
        writeDataDouble(stream, this.inputDoubleW);
    }

在我们的 CustomOutputType 中

import java.sql.Date;
import java.sql.SQLData;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;

public class CustomOutputType implements SQLData {

    String sql_type = "SCHEMA_DBA.TY_CUSTOM_OUTPUT";

    String inputStringA;
    Long inputLongB;
    Date inputDataC;
    Double inputDoubleD;

    public String getInputStringA() {
        return inputStringA;
    }

    public void setInputStringA(String inputStringA) {
        this.inputStringA = inputStringA;
    }

    public Long getInputLongB() {
        return inputLongB;
    }

    public void setInputLongB(Long inputLongB) {
        this.inputLongB = inputLongB;
    }

    public Date getInputDataC() {
        return inputDataC;
    }

    public void setInputDataC(Date inputDataC) {
        this.inputDataC = inputDataC;
    }

    public Double getInputDoubleD() {
        return inputDoubleD;
    }

    public void setInputDoubleD(Double inputDoubleD) {
        this.inputDoubleD = inputDoubleD;
    }

    // -- sqlType -- v
    @Override
    public String getSQLTypeName() throws SQLException {
        return sql_type;
    }

    public String getSqlType() {
        return sql_type;
    }
    // -- sqlType -- ^

    // -- read/write Data utility-- v
    public Long readDataLong(SQLInput stream) throws SQLException {
        Long dataLong = stream.readLong();
        if (stream.wasNull()) {
            dataLong = null;
        }
        return dataLong;
    }

    public Double readDataDouble(SQLInput stream) throws SQLException {
        Double dataDouble = stream.readDouble();
        if (stream.wasNull()) {
            dataDouble = null;
        }
        return dataDouble;
    }

    public void writeDataLong(SQLOutput stream, Long dataLong) throws SQLException {
        if (dataLong != null) {
            stream.writeLong(dataLong);
        } else {
            stream.writeObject(null);
        }
    }

    public void writeDataDouble(SQLOutput stream, Double dataDouble) throws SQLException {
        if (dataDouble != null) {
            stream.writeDouble(dataDouble);
        } else {
            stream.writeObject(null);
        }
    }
    // -- read/write Data utility-- ^

    @Override
    public void readSQL(SQLInput stream, String typeName) throws SQLException {
        this.sql_type = typeName;
        this.inputStringA = stream.readString();
        this.inputLongB = readDataLong(stream);
        this.inputDataC = stream.readDate();
        this.inputDoubleD = readDataDouble(stream);
    }

    @Override
    public void writeSQL(SQLOutput stream) throws SQLException {
        stream.writeString(this.inputStringA);
        writeDataLong(stream, this.inputLongB);
        stream.writeDate(this.inputDataC);
        writeDataDouble(stream, this.inputDoubleD);
    }

注意事项:

  1. 输出对象使用声明

    typeMap.put("SCHEMA_DBA.FI_TY_CUSTOM_OUTPUT", Class.forName("com.myproject.view.CustomOutputType"));

了解使用的数据对象是什么 2)输入对象使用声明 公共类 CustomInputType 实现 SQLData {

String sql_type = "SCHEMA_DBA.TY_CUSTOM_INPUT";

了解使用的数据对象是什么 3) 要为 Stream SQLInput 获取 NULL,您可以这样做

Long dataLong = stream.readLong();

if (stream.wasNull()) {
    dataLong = null;
}

所以 readLong 返回 0 如果数据库中为 NULL 但在使用 wasNull 之后你可以强制 java 中的值返回 null 如果数据库中实际上是 NULL

  1. 要为 Stream SQLOutput 设置 NULL,您可以这样做

    if (dataLong != null) { stream.writeLong(dataLong); } 别的 { stream.writeObject(null); }

所以如果值不为空,那么你可以使用带有long的writeLong,但是如果java中的值为空,你必须使用带有空参数的writeObject在数据库中设置NULL

干杯