Results 1 to 5 of 5

Thread: Multiple calls to StoredProcedure using same connection

  1. #1
    Join Date
    Jan 2006
    Posts
    16

    Default Multiple calls to StoredProcedure using same connection

    I have extended StoredProcedure class and have been calling it with different values within a loop. The StoredProcedure has been instantiated outside of the loop using it's constructor. This seems to open and close connection to the database everytime I call the execute() method of the extended class, which is an expensive proposition from resource standpoint. Is there a way to do this and make it use the same connection within the loop?

    Following is the extended class.

    public class CallInsertCpnScheduleItem extends StoredProcedure {
    private static final String INSERT_SCHEDULE_ITEM = "InsertProdScheduleItem";

    public CallInsertCpnScheduleItem(SybDataSource dataSource) {
    super(dataSource, INSERT_SCHEDULE_ITEM);
    declareParameter(new SqlParameter("product", Types.VARCHAR));
    declareParameter(new SqlParameter("beginDate", Types.DATE));
    declareParameter(new SqlParameter("endDate", Types.DATE));
    declareParameter(new SqlParameter("prodPrice", Types.DOUBLE));
    declareParameter(new SqlOutParameter("err", Types.INTEGER));
    compile();
    }

    public int execute(String product, Date beginDate, Date endDate, Double prodPrice) {
    Map inParams = new HashMap(4);
    inParams.put("product", new String(product));
    inParams.put("beginDate", new java.sql.Date(beginDate.getTime()));
    inParams.put("endDate", new java.sql.Date(endDate.getTime()));
    inParams.put("prodPrice", new Double(prodPrice.doubleValue()));
    Map outParams = this.execute(inParams);
    if (outParams.size() > 0) {
    System.out.println("Returned Stored Procedure Value is: " + ((Integer)outParams.get("err")).intValue());
    return ((Integer)outParams.get("err")).intValue();
    }
    else
    return -9999;
    }
    }


    main

    CallInsertProdScheduleItem cicsi = new CallInsertProdScheduleItem(sybDataSource);
    for (i=0; i<5; i++)
    {
    ....
    ....
    result = cicsi.execute(strProduct, dtBeginDate, dtEndDate, objDblProdPrice);
    ....
    ....
    }

  2. #2
    Join Date
    Feb 2005
    Location
    Boston, MA
    Posts
    1,142

    Default

    Take a look at this thread
    Bill

  3. #3
    Join Date
    Jan 2006
    Posts
    16

    Default

    I did look at SingleConnectionDataSource option in the past and again after your post. My issue is that dataSource is obtained using JNDIObjectFactoryBean as following.

    <bean id="jndiDBTemplate" class="org.springframework.jndi.JndiTemplate">
    <property name="environment">
    <props>
    <prop key="java.naming.factory.object">${DB_OBJECT_FACTO RIES}</prop>
    <prop key="java.naming.factory.initial">${LDAP_INITIAL_C ONTEXT_FACTORY}</prop>
    <prop key="java.naming.provider.url">${DB_PROVIDER_URL}</prop>
    </props>
    </property>
    </bean>

    <bean id="jndiLdapBean" class="org.springframework.jndi.JndiObjectFactoryB ean">
    <property name="jndiTemplate"><ref bean="jndiDBTemplate"/></property>
    <property name="jndiName"> <value>sybaseServerName=${NPA_DB_SVR}</value> </property>
    </bean>


    This gives me the "DataSource" of my jdbc driver (which SybDataSource). I have to do it this way because it is defined on an LDAP server. Now, if I want to configuere "SingleConnectionDataSource" how would I define that in the Application Context since it only takes driverclass, url, username and password as the parameters. It has connectionProperties but I am not sure how I can use that either.

    Another issue I have using SingleConnectionDataSource is that I need to call a StoredProcedure (via extending Spring's StoredProcedure class) which requires DataSource as an argument to it's constructor in the example described in the first post of this thread. If I provide SybDataSource to that, how will SingleConnectionDataSource come into play anyways?

    What I am doing is something very simple using JDBC and I am hoping Spring will keep it simple also. Any ideas anyone?

  4. #4
    Join Date
    Feb 2005
    Location
    Boston, MA
    Posts
    1,142

    Default

    Using SingleConnectionDataSource doesn't really fit into the Spring way. You don't use a SingleConnectionDataSource in your application context, you use an existing datasource to get a connection, create a SingleConnectionDataSource using new, passing the recently created session, set the SingleConnectionDataSource on the StoredProcedure and then call the StoredProcedure. This is very ugly and not very thread safe. In order to make it thread safe you have to create the StoredProcedure locally. So basically it would look like this:

    Code:
      Connection singleConnection = getDataSource().getConnection();
      DataSource ds = new SingleConnectionDataSource(singleConnection);
      MyStoredProcedure sp = new MyStoredProcedure(ds);
      // Make sp call.
      singleConnection.close();
    You can make this a little less ugly by using JdbcTemplate.execute:

    Code:
    getJdbcTemplate().execute(new ConnectionCallback() {
      public Object doInConnection(Connection con) throws JMSException {
        DataSource ds = new SingleConnectionDataSource(con);
        MyStoredProcedure sp = new MyStoredProcedure(ds);
        // Make sp call, and any other calls you need against the connection, including direct JDBC
        return null;
      }
    });
    There are several versions of the execute method which can provide some JDBC object that you can make several calls against. When you feel that Spring just isn't fitting the bill, you can fallback to direct JDBC calls, use JdbcTemplate.execute. It still provide Spring transaction support, exception translation, etc.

    Using a transaction proxy is more spring like because you take care of making sure the method call uses only one connection outside of the actual object. It doesn't invade your code.

    Spring is designed to use J2EE APIs (like JDBC, JMS, EJB) the way they were intended. You get a resource from some object, you use it, then you release it. Performance is typically enchanced by using pooling or caching. But if you need to go further, tying a database call using a transaction proxy can go one step further and use one connection per business method.

    I realize this sometimes makes Spring heavier than your typical J2EE code. But Spring is consistant in how it implements these things. It isn't however alwayst the most efficient way or the easiest. What it does provide you is a consistent exception handling mechanism while reducing boilerplate code in your actual business methods. In the long run it makes such code more testable and reusable.

    I've been through exactly what you are going through. Trying to find a way around some of the limitations of the way Spring does things. It tends to be more static, with most dependencies resolved at start up. More use of singletons. Trying to solve the infrastructure and performance issues outside of your actual code.

    Easing into Spring can sometimes be painful. And if you read any of the critiques of Spring, can produce practices that seem like overkill, or creates another set of problems. And it does.

    Where Spring really starts to show its savings is when your application has dozens of stored procedure calls, several DAOs, multiple databases, multiple custom configuration files, tons of boilerplate code for reading config files and doing resource lookups. I've converted such an application from the old way to the Spring way. And now I have all of my objects in one logical context spread across 4 XML files. And when I load it into IDEA or Eclipse using a Spring plugin, I now have a very good idea of how my large collection of services relate to each other. And my components are unit testable if needed. And anytime I want, I can throw away the container and wire up my objects by hand (although personally I don't think I'd want to, given the size of my project)

    If Spring isn't really working for you, I advise you to step back and use it less. Just use JdbcTemplate and maybe StoredProcedure. Don't doing any wiring with the container or XML. That is an area that I've seen trip up the most experienced J2EE developers trying to fit Spring into their application.

    HTH
    Bill

  5. #5
    Join Date
    Jan 2006
    Posts
    16

    Default

    Thanks for this excellent reply. I am a strong advocate of using Spring where I work and believe me there are objections. I did get this to work but like you said, I don't like it because it is not thread-safe. I will take your suggestions and make it as thread-safe as possible. Thank you so much.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •