2

I would like to call a stored procedure (Oracle). As I my procedure calls are dynamical, I need to manage the procedures parameters dynamically. The problem is that I would like to avoid using the instanceof keyword since it does not work well with primary types. Is there a cleaner way to call a such procedure?

    public void executeProcedure(StoredProcedure proc) {        
        LinkedList<ProcedureParameter<?>> parameters = proc.getParameters();

        CallableStatement statement = connection.prepareCall("{ call MY_PACKAGE.MY_PROCEDURE( ?, ?, ? ) }");

        for (int i = 0; i < parameters.size(); i++) {
            Object paramValue = parameters.get(i).getValue();

            // Beginning of smelly code

            if (paramValue instanceof String) {
                statement.setString(i + 1, (String) paramValue);
            }
            else if (paramValue instanceof ...) {
                ...
            }
            else {
                ...
            }

            // End of smelly code
        }

        statement.execute();            
    }

 

    public class ProcedureParameter<E> {
        private String name;
        private E value;

        public ProcedureParameter(String name) {
            this.name = name;
        }

        public ProcedureParameter(String name, E value) {
            this.name = name;
            this.value = value;
        }

        // Getters and setters
    }

Thank you for any idea.

3
  • If your only problem is with primitive types, I would suggest you just use their object wrapper equivalents and make life easy for you Commented Jun 21, 2012 at 13:57
  • 2
    @ControlAltDel I think the issue is more that when adding a parameter to a Statement, you have to specify the type - ie statement.setString, statement.setInteger, etc. Commented Jun 21, 2012 at 14:00
  • @ControlAltDel That's a good idea, but the problem scope is wider; I mean, the amount of possible parameters types is quite big, and I am looking for a solution that would avoid a long if-else sequence. Commented Jun 21, 2012 at 14:04

3 Answers 3

1

I think it could help you to implement needed functionality without instanceof: http://en.wikipedia.org/wiki/Visitor_pattern

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, however it won't help me since I don't use custom types but primary types or "java" types (like String)
1

You could use reflection, although this isn't good practice because it's slower and prevents the compiler from checking to make sure the method calls are correct. You would map each class to its corresponding CallableStatement method. For example String would be mapped to "setString".

List<ProcedureParameter<?>> parameters = proc.getParameters();
CallableStatement statement = connection.prepareCall("{ call MY_PACKAGE.MY_PROCEDURE( ?, ?, ? ) }");

Map<Class<?>, String> methods = new HashMap<Class<?>, String>();
methods.put(String.class, "setString");
//...

for (int i = 0; i < parameters.size(); i++) {
  Object paramValue = parameters.get(i).getValue();
  Class<?> paramValueClass = paramValue.getClass();
  String stmtMethod = methods.get(paramValueClass);
  if (stmtMethod != null){
    Method method = statement.getClass().getMethod(stmtMethod, int.class, paramValueClass);
    method.invoke(statement, i+1, paramValue);
  } else {
    //error
  }
}

2 Comments

Well, that solution seems to be even heavier than the "if-else" solution... Thank you anyway :)
@dounyy Yes I agree I just made this answer because I'm bored. :) The if/else solution is also very readable--if I am new to the code base, I can easily see what is going on. If this is all refactored and gets hidden behind some other classes, then it makes it harder to figure out what is going on at a glance.
1

I will implement another solution, that is probably not be best one, but in my opinion, not smelly though.

As StoredProcedure is an interface, each stored procedure implements this interface. Thus, each implementation will contain a method that returns the call ... statement, as the developer knows the type of the parameters needed for the procedure he implements.

1 Comment

would you mind expanding a little more on this answer? I am very new to using StoredProcedures and trying to wrap my head around this. More searching, i found this implementation, is it something similar? codeguru.com/csharp/csharp/cs_misc/sampleprograms/article.php/… Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.