Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 多次执行StoredProcess_Java_Spring_Oracle_Function - Fatal编程技术网

Java 多次执行StoredProcess

Java 多次执行StoredProcess,java,spring,oracle,function,Java,Spring,Oracle,Function,我有下面的代码,它创建了StoredProcedure的子类并执行它。我想要实现的是将同一对象与新SQL和新参数一起使用多次。不幸的是,当我设置新SQL并声明新参数时,我得到了一个异常 是否有可能“泛化”类以使用新参数执行多个SQL在我的特定示例中,不止一个问题 代码 package procedures; import org.springframework.jdbc.core.SqlOutParameter; import org.springframework.jdbc.core.Sql

我有下面的代码,它创建了
StoredProcedure
的子类并执行它。我想要实现的是将同一对象与新SQL和新参数一起使用多次。不幸的是,当我设置新SQL并声明新参数时,我得到了一个异常

是否有可能“泛化”类以使用新参数执行多个SQL在我的特定示例中,不止一个问题

代码

package procedures;

import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.object.StoredProcedure;

import javax.sql.DataSource;
import java.sql.Types;
import java.util.HashMap;
import java.util.Map;

public class MyProcedure extends StoredProcedure {

    private static String SQL = "hr.get_size";

    public MyProcedure(DataSource dataSource) {
        super(dataSource, SQL);
        declareParameter(new SqlOutParameter("param_out", Types.NUMERIC));
        declareParameter(new SqlParameter("param_in", Types.VARCHAR));
        setFunction(true);
        compile();
    }

    public Object execute(String tableName) {
        Map in = new HashMap();
        in.put("param_in", tableName);
        Map out = execute(in);
        if (!out.isEmpty()) {
            return out.get("param_out");
        } else {
            return null;
        }
    }
}
引发异常的调用:

public static void main(String[] args) {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationConfig.class);
    MyProcedure myProcedure = applicationContext.getBean(MyProcedure.class);
    System.out.println(myProcedure.execute("employees"));

    myProcedure.setSql("hr.get_all_tables");
    myProcedure.declareParameter(new SqlOutParameter("param_out", Types.VARCHAR));
    myProcedure.setFunction(true);
    myProcedure.compile();
    System.out.println(myProcedure.execute());
}
Exception in thread "main" org.springframework.dao.InvalidDataAccessApiUsageException: Cannot add parameters once the query is compiled
    at org.springframework.jdbc.object.RdbmsOperation.declareParameter(RdbmsOperation.java:278)
    at org.springframework.jdbc.object.StoredProcedure.declareParameter(StoredProcedure.java:99)
    at main.Main.main(Main.java:20)
    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:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
例外情况:

public static void main(String[] args) {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationConfig.class);
    MyProcedure myProcedure = applicationContext.getBean(MyProcedure.class);
    System.out.println(myProcedure.execute("employees"));

    myProcedure.setSql("hr.get_all_tables");
    myProcedure.declareParameter(new SqlOutParameter("param_out", Types.VARCHAR));
    myProcedure.setFunction(true);
    myProcedure.compile();
    System.out.println(myProcedure.execute());
}
Exception in thread "main" org.springframework.dao.InvalidDataAccessApiUsageException: Cannot add parameters once the query is compiled
    at org.springframework.jdbc.object.RdbmsOperation.declareParameter(RdbmsOperation.java:278)
    at org.springframework.jdbc.object.StoredProcedure.declareParameter(StoredProcedure.java:99)
    at main.Main.main(Main.java:20)
    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:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

您的
MyProcedure
类不应扩展
StoredProcedure
,而应委托给它


我认为您所做的是滥用类扩展的一个例子。如果您的子类要尊重超类的行为,则只应扩展类或接口(请参阅)。
StoredProcedure
类封装了单个过程,并且是只读的,这为使用它的类提供了一定的保证。您的类可以在后台更改过程和参数,因此这是另一回事

您应该将
StoredProcedure
设置为类的私有成员,并委派对它的调用(请参阅)

当您需要访问一个新的存储过程时,只需扔掉旧的
StoredProcedure
对象和另一个
new
对象。如果需要,您可以创建一个匿名内部类:

    StoredProcedure sp = new StoredProcedure(ds, SQL) {
        public Object execute(String tableName) {
            Map in = new HashMap();
            in.put("param_in", tableName);
            Map out = execute(in);
            if (!out.isEmpty()) {
                return out.get("param_out");
            } else {
                return null;
            }
        }
    };
如果代码中的某些内容需要访问实际的存储过程对象,则可以提供一个getter来公开它


另请参阅本文:

StoredProcess
类是抽象类-我无法创建它的实例。我添加了一个创建匿名类的示例。但最后,您必须为每个过程创建一个新的
StoredProcedure
对象。我不会浪费时间试图找到避免这样做的方法。