sql >> Databasteknik >  >> RDS >> Mysql

IBM Worklight - Hur får man ut parametern OUT när man anropar en lagrad procedur?

Möjligheten att anropa java från adaptrarna erbjuder en hel del flexibilitet, inklusive möjligheten att anropa din egen JDBC-lagrade proc-implementering. Genom att använda detta kan vi anropa de lagrade processerna med OUT SYS_REFCURSOR definierade och få resultatet satt tillbaka som JSON. En jdbc-datakälla måste skapas på din appserver (Liberty, Websphere, etc..) Se metoderna som refereras till i StoredProcedure java-klassen för att exekvera den lagrade processen och få tillbaka data som JSON. Använder Apache dbutils och Jackson för JSON-grejer.

CREATE PACKAGE "HR"."HR_DATA" IS  -- Declare types, variables, constants, exceptions, cursors, 
  -- and subprograms that can be referenced from outside the package.

  PROCEDURE "GETCURSORS" (
    "DEP_ID" IN NUMBER, 
    "EMPLOYEES_C" OUT SYS_REFCURSOR, 
    "DEPENDENTS_C" OUT SYS_REFCURSOR);
END "HR_DATA";

Adapterkod:

function getEmployeesByDep(departmentId){

var storedProcedure = new Packages.com.samnunnally.dao.StoredProcedure();

storedProcedure.setDataSource("jdbc/hr_datasource");
storedProcedure.setStoredProcName("HR.HR_DATA");
storedProcedure.addParameter(0, departmentId, false);
storedProcedure.addOutParameter(1, Packages.oracle.jdbc.OracleTypes.CURSOR);
storedProcedure.addOutParameter(2, Packages.oracle.jdbc.OracleTypes.CURSOR);

var rsHandler = new Packages.org.apache.commons.dbutils.handlers.MapListHandler();
storedProcedure.execute(rsHandler);

return {
        result : 
            {   
                EMPLOYEES : storedProcedure.getJsonParameterValue(1),
                DEPENDENTS : storedProcedure.getJsonParameterValue(2)
            } 
    };


}

Java JDBC-klass:

package com.samnunnally.dao;

import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.KeyedHandler;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.annotate.JsonRawValue;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

/**
 * @author Sam Nunnally
 *
 */
public class StoredProcedure {

    private String dataSource = "";
    private String storedProcName = "";
    private ArrayList<Parameter> parameters = null;

    private Object resultSet = null;

    private boolean autoCommit = true;

    private final static String CALL_STRING = "{call "; 
    private final static String CALL_OPEN_PAREN = "(";
    private final static String CALL_PARM = "?";
    private final static String CALL_COMMA = ",";
    private final static String CALL_CLOSE = ")}";

    private class Parameter{
        private int index = -1;

        private boolean outParamter = false;

        private Object value = null;

        private Integer type = null;

        /**
         * @return the index
         */
        public int getIndex() {
            return index;
        }
        /**
         * @param index the index to set
         */
        public void setIndex(int index) {
            this.index = index;
        }
        /**
         * @return the outParamter
         */
        public boolean isOutParamter() {
            return outParamter;
        }
        /**
         * @param outParamter the outParamter to set
         */
        public void setOutParamter(boolean outParamter) {
            this.outParamter = outParamter;
        }
        /**
         * @return the value
         */
        public Object getValue() {
            return value;
        }
        /**
         * @param value the value to set
         */
        public void setValue(Object value) {
            this.value = value;
        }
        /**
         * @return the type
         */
        public int getType() {
            return type;
        }
        /**
         * @param type the type to set
         */
        public void setType(int type) {
            this.type = type;
        }


    }

    public void execute() throws NamingException, SQLException{
        this.execute(new KeyedHandler<Object>());
    }

    public void execute(ResultSetHandler<?> rsHandler) throws NamingException, SQLException{

        Connection connection = null;
        try {
            Context ctx = new InitialContext();

            DataSource ds = (DataSource)ctx.lookup(dataSource);

            connection = ds.getConnection();

            connection.setAutoCommit(autoCommit);

            String call = createCallString();

            CallableStatement cs = connection.prepareCall(call);

            int i=1;
            for (Parameter p : this.getParameters()) {
                if(p.isOutParamter()){
                    cs.registerOutParameter(i, p.getType());
                }
                else{
                    cs.setObject(i, p.getValue());
                }

                i++;
            }

            cs.execute();

            i=1;
            for (Parameter p : this.getParameters()) {
                if(p.isOutParamter()){

                    if(p.getType() == -10/*oracle.jdbc.OracleTypes.CURSOR*/){
                        p.setValue(rsHandler.handle((ResultSet)cs.getObject(i)));
                    }
                    else{
                        p.setValue(cs.getObject(i));
                    }
                }
                i++;
            }

            /*
             * Could do some BeanHandler implementation for <T> T
             * 
            Class Summary 
            AbstractKeyedHandler<K,V> ResultSetHandler implementation that returns a Map. 
            AbstractListHandler<T> Abstract class that simplify development of ResultSetHandler classes that convert ResultSet into List. 
            ArrayHandler ResultSetHandler implementation that converts a ResultSet into an Object[]. 
            ArrayListHandler ResultSetHandler implementation that converts the ResultSet into a List of Object[]s. 
            BeanHandler<T> ResultSetHandler implementation that converts the first ResultSet row into a JavaBean. 
            BeanListHandler<T> ResultSetHandler implementation that converts a ResultSet into a List of beans. 
            BeanMapHandler<K,V> ResultSetHandler implementation that returns a Map of Beans. 
            ColumnListHandler<T> ResultSetHandler implementation that converts one ResultSet column into a List of Objects. 
            KeyedHandler<K> ResultSetHandler implementation that returns a Map of Maps. 
            MapHandler ResultSetHandler implementation that converts the first ResultSet row into a Map. 
            MapListHandler ResultSetHandler implementation that converts a ResultSet into a List of Maps. 
            ScalarHandler<T> ResultSetHandler implementation that converts one ResultSet column into an Object. 
                 */
            ResultSet rs = cs.getResultSet();
            if(rs != null){
                resultSet = rsHandler.handle(rs);
            }

        } 
        finally{
            if(connection != null){
                connection.close();
            }
        }
    }

    private String createCallString(){

        StringBuffer sb = new StringBuffer();

        int parmCnt = this.getParameters().size();

        sb.append(CALL_STRING)
            .append(storedProcName)
            .append(CALL_OPEN_PAREN);

        for(int i = 0;i<parmCnt;i++){
            sb.append(CALL_PARM);
            if(parmCnt > i + 1){
                sb.append(CALL_COMMA);
            }
        }

        sb.append(CALL_CLOSE);
        return sb.toString();
    }

    /**
     * @return the dataSource
     */
    public String getDataSource() {
        return dataSource;
    }

    /**
     * @param dataSource the dataSource to set
     */
    public void setDataSource(final String dataSource) {
        this.dataSource = dataSource;
    }

    /**
     * @return the storedProc
     */
    public String getStoredProcName() {
        return storedProcName;
    }

    /**
     * @param storedProc the storedProc to set
     */
    public void setStoredProcName(final String storedProcName) {
        this.storedProcName = storedProcName;
    }

    /**
     * @return the autoCommit
     */
    public boolean isAutoCommit() {
        return autoCommit;
    }

    /**
     * @param autoCommit the autoCommit to set
     */
    public void setAutoCommit(boolean autoCommit) {
        this.autoCommit = autoCommit;
    }

    /**
     * @return the resultSet
     */
    public Object getResultSet() {
        return resultSet;
    }

    /**
     * @return the parameters
     */
    private ArrayList<Parameter> getParameters() {
        if(parameters == null){
            parameters = new ArrayList<StoredProcedure.Parameter>();
        }
        return parameters;
    }



    /**
     * @param index - the first parameter is 0, the second is 1, and so on
     * @param value
     * @param isOutParam
     */
    public void addParameter(int index, Object value, boolean isOutParam){
        Parameter p = new Parameter();

        p.setIndex(index);
        p.setValue(value);
        p.setOutParamter(isOutParam);
        p.setType(determineSqlType(value));

        this.getParameters().add(index, p);
    }


    /**
     * @param index - the first parameter is 0, the second is 1, and so on
     * @param type - java.sql.Types int value of the parameter
     */
    public void addOutParameter(int index, int type){
        Parameter p = new Parameter();

        p.setIndex(index);
        p.setType(type);
        p.setOutParamter(true);

        this.getParameters().add(index, p);
    }

    /**
     * @param index - the first parameter is 0, the second is 1, and so on
     * @param type - java.sql.Types value of the parameter
     */
    public void addOutParameter(int index, Object type){
        Parameter p = new Parameter();

        p.setIndex(index);
        p.setType((int)type);
        p.setOutParamter(true);

        this.getParameters().add(index, p);
    }

    public Object getParameter(int index){
        return this.getParameters().get(index);
    }

    @JsonProperty("raw")
    @JsonRawValue
    public String getJsonResultSet() throws JsonGenerationException, JsonMappingException, IOException{


        String result = "{}";

        if(this.getResultSet() != null){
            ObjectMapper mapper = new ObjectMapper();

            result = mapper.writeValueAsString(this.getResultSet());
        }

        return result;
    }

    @JsonProperty("raw")
    @JsonRawValue
    public String getJsonParameterValue(int index) throws JsonGenerationException, JsonMappingException, IOException{

        String result = "{}";

        Parameter parm = this.getParameters().get(index);
        if(parm != null && parm.getValue() != null){
            ObjectMapper mapper = new ObjectMapper();

            result = mapper.writeValueAsString(parm.getValue());
        }

        return result;
    }


    /**
     * 
     * Determines SqlType of object. throws exception if unknown
     * 
     * NOTE: this is not meant to be a complete list, just picked most
     * common types to start with.
     * 
     * @param obj
     * 
     * @return $returnType
     * 
     */
    public static int determineSqlType(Object obj) {
        int sqlType = Types.VARCHAR;
        if (obj == null) {
            // assuming a string if object is null
            sqlType = Types.VARCHAR;
        } else if (obj instanceof java.lang.String) {
            sqlType = Types.VARCHAR;
        } else if (obj instanceof java.lang.Integer) {
            sqlType = Types.INTEGER;
        } else if (obj instanceof java.lang.Double) {
            sqlType = Types.DOUBLE;
        } else if (obj instanceof java.lang.Float) {
            sqlType = Types.FLOAT;
        } else if (obj instanceof java.io.InputStream) {
            sqlType = Types.LONGVARBINARY;
        } else if (obj instanceof java.math.BigDecimal) {
            sqlType = Types.DECIMAL;
        } else if (obj instanceof java.math.BigInteger) {
            sqlType = Types.BIGINT;
        } else if (obj instanceof java.util.Date) {
            sqlType = Types.DATE;
        } else if (obj instanceof java.sql.Date) {
            sqlType = Types.DATE;
        } else if (obj instanceof java.sql.Timestamp) {
            sqlType = Types.TIMESTAMP;
        } else if (obj instanceof java.sql.ResultSet) {
            //oracle.jdbc.OracleTypes.CURSOR
            sqlType = -10;
        } else if (obj instanceof java.sql.Blob) {
            sqlType = Types.BLOB;
        } else if (obj instanceof java.sql.Clob) {
            sqlType = Types.CLOB;
        } else {
            sqlType = Types.OTHER;
        }
        return sqlType;
    }

}


  1. Oracle lagrad procedur med parametrar för IN-sats

  2. Migrera från traditionell replikering till GTID

  3. PHP/SQL-databas som frågar efter god praxis och säkerhet

  4. DSN-filer och IRI-programvara