我有以下代码创建StoredProcedure
的子类并执行它。我想要实现的是将同一个对象与新SQL和新参数一起使用多次。不幸的是,当我设置新的SQL并声明新的参数时,我得到了一个异常。
在某种程度上可以" generify"用新参数执行多个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)
答案 0 :(得分:2)
您的MyProcedure
课程不应该延长StoredProcedure
,而是委托给它。
我认为你所做的是滥用类扩展的一个例子。如果你的子类要尊重超类的行为,你应该只扩展一个类或接口(参见Liskov Substitution Principal)。 StoredProcedure
类封装了一个过程并且是只读的,它为使用它的类提供了某些保证。你的班级可以在后台更改程序和参数,所以这是另一回事。
您应该让StoredProcedure
成为您班级的私人成员并委托对其进行调用(请参阅Delegation Pattern)。
当您需要访问新的存储过程时,您只需丢弃旧的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来公开它。