PreparedStatement reuse

Is it possible to use a PreparedStatement after its resultset has been processed? It seems to me like once you iterate through the ResultSet the PreparedStatement can not be executed again with a different set of parameters. Is this correct? I'm using the JdbcOdbcDriver, but I am also looking at the Sybase Jconnect driver. Could this be a driver issue?
here is some pseudocode:
statement = connection.prepareStatement("Select ....");
for (i = 0; i < 10; ++i) {
statement.setInt(1, intVal);
statement.setString(2, strVal);
statement.execute();
result = statement.getResultSet();
process the results
Problem is that with the 2nd iteration I get a java.sql.SQLException: Invalid handle.

Yes, you can. In my programs I generally call prepareStatement() in the class initialization, then reuse the PreparedStatement whenever I need it. I've never had an invalid handle error. My code usually says
result = statement.executeQuery()
instead of what you have there, but I wouldn't expect that to make any difference.

Similar Messages

  • Response time low to display 2700 records

    In my program , i have tried to display 2700 records from Database using JSP.
    But the response time is very slow. How do i overcome this problem.
    My architecture is
    JSP - EJB - HelperClass - DB.

    Find out where the performance bottleneck is
    1) Database -> use PreparedStatements,
    reuse an open database connection
    2) JSP -> Check your string handling, use StringBuffer() for appending
    lots of strings together
    3) Network response -> Maybe try defining a static IP address for your
    server
    regards,
    Owen

  • Reuse of preparedstatements and the connection pool

    It seems useful (for performance reasons) to reuse a prepared statement in
    subsequent calls to the database. In WebLogic, however, after each call we
    return the Connection object to the WebLogic connection pool. A prepared
    statement is created on a specific Connection object. The next time we want
    to use the same query we get a Connection from the pool, which might be
    another instance of the Connection class. Therefor it seems impossible or at
    least dangerous to reuse the same prepared statement. Even in the case this
    would work we're indirectly using the other Connection, which we already
    returned to the pool and which could be retrieved from the pool by someone
    else. So, can't we reuse preparedstatements ?

    Hi Raja,
    Currently the only bullet-proof way to make sure that all statements are
    cached is to set the cache size to a number of possible prepared statements
    in the application.
    The only consequence of increased cache size is growing amount of
    memory required by a server instance.
    Regards,
    Slava Imeshev
    "Rajiv Jauhari" <[email protected]> wrote in message
    news:[email protected]...
    Is there an easy way to tell whether the prepared statement cache size one
    has set is
    appropriate? Some way to monitor cache hit rate or usage count (i.e., the
    actual number of statements cached) while running a load test? I'm using
    Weblogic 6.1sp3 and Oracle 8.1.7.4.
    Another way to think of this question is: is there a negative impact ifthe
    cache size is set too large?
    In the case of Oracle I believe one might run out of cursors, but is there
    any other negative consequence that you know of?
    Thanks,
    Rajiv
    "Joseph Weinstein" <[email protected]> wrote in message
    news:[email protected]...
    Vyas wrote:
    If multiples (of the same statement) can be cached would it not result
    in too many
    prepared statements of the same type in the cache ?
    This could happen
    1. When a load test is done when all the threads start doing exactly
    the
    same work.
    Because of contention everybody gets their own statement copy(theoritically, even
    if in practice it may not exactly happen like that). In such a case
    you
    are going
    to create load on the database in terms of open cursors.Each thread will get it's own connection, and the statement cache isper-connection.
    Cursors, in Oracle's case, do need to be configured to support acache-full of
    retained statements. Alternately, the cache should be set to a smallenough size to
    require only as many cursors as the DBMS will allow per connection.
    Another issue is what happens when the cache limit is hit ?
    In the above example let's say cache limit is 50 and I am doing 50
    user
    load test.
    because of load test let's say the cache gets filled with 50 of the
    same
    statement.
    When load test moves to the next sequence of action requiring a
    diffrent
    statement
    what happens to the cache ?
    thanks
    VyasThe only way a given connection's statement cache will get a duplicatestatement
    is if some single JDBC thread required multiple copies of the samestatement. A
    multi-user test will usually just ensure that each pooled connectioncaches the
    same selection of different statements that the test user used. If thetest user
    just repeatedly makes and uses one statement, the first time they do it,the
    statement will be cached, and every subsequent repeat of the user codewill get
    the same cached statement. The cache will still have 49 empty slotswaiting for
    different statements. Currently the cache is simple-minded. It is a
    fixed
    (configurable)
    size per connection, and the first N prepared/callable statements getcached for the
    life of the pooled connection that created them. All other subsequentstatements will
    be made and closed on a per-connection-use basis. Therefore, it can bethat a startup
    or stress load that runs before standard runtime service, and which usessignificantly
    different a statement profile could populate the cache with rarely-usedwasted statements.
    If I were a customer in this circumstance, I would either prime thecaches, by determining
    which statements I wanted cached, and then running a startup class thatreserved all the
    pool connections, and made these statements on each before closing them.Alternately,
    after startup/stress I would reset the pool, and allow the runtime load
    to
    fill the cache of
    the regenerated pool.
    Joe Weinstein at B.E.A.
    thanks
    Vyas
    Joseph Weinstein <[email protected]> wrote:
    JS wrote:
    It seems useful (for performance reasons) to reuse a prepared
    statement
    in
    subsequent calls to the database. In WebLogic, however, after each
    call
    we
    return the Connection object to the WebLogic connection pool. A
    prepared
    statement is created on a specific Connection object. The next timewe
    want
    to use the same query we get a Connection from the pool, which
    might
    be
    another instance of the Connection class. Therefor it seemsimpossible
    or at
    least dangerous to reuse the same prepared statement. Even in the
    case
    this
    would work we're indirectly using the other Connection, which we
    already
    returned to the pool and which could be retrieved from the pool bysomeone
    else. So, can't we reuse preparedstatements ?We already have you covered! Weblogic caches PreparedStatements along
    with the pooled connection they came from. Every time you obtain a
    pool
    connection and run a prepareStatement() or prepareCall(), we willtransparently
    give you a previously made statement, if the SQL exactly matches, andno
    other place in the current thread stack is using that statement(multiples
    can
    be cached)
    You are correct, of course, that statements you have should only
    be
    useable
    to you while you have the connection from which they came. We have
    you
    covered
    there too. If you were to try to use any prepared statement that
    you'd
    gotten
    from
    a pool connection after you'd put the connection back into the pool,those
    statements
    would throw an exception saying that they had been made inoperable atthe
    time
    you'd closed the connection.
    Joe Weinstein at B.E.A.

  • Reusing PreparedStatement

    Could someone comment on my code please. I'm reusing the PreparedStatement (delete) below for different queries before closing the PreparedStatement (delete is closed in this.close()). The API for Statement.close() states:
    Releases this Statement object's database and JDBC resources immediately instead of waiting for this to happen when it is automatically closed. It is generally good practice to release resources as soon as you are finished with them to avoid tying up database resources.
    ...but what resources would be wasted if the PreparedStatement is reused AND is this opening the app up to innefficency/overhead?
    Your reply is appreciated. Code below....
    public boolean cascadeDeleteRfxForm() throws SQLException, Exception{
    boolean deleteFlag=true;
    try{
    //create connection
    this.createConnection();
    //set autocommit to fals - allows batch commit/rollback
    con.setAutoCommit(false);
    //create prepare statement from string
    delete=con.prepareStatement(deleteRfxItemAttr);
    delete.setString(1, orgId);
    delete.setString(2, rfxName);
    delete.setString(3, rfxUniqueId);
    delete.setString(4, revNbr);
    //execute prepared statement
    delete.execute();
    //create prepared statment from string
    delete=con.prepareStatement(deleteRfxAttr);
    delete.setString(1, orgId);
    delete.setString(2, rfxName);
    delete.setString(3, rfxUniqueId);
    delete.setString(4, revNbr);
    //execute prepared statement
    delete.execute();
    //create prepared statment from string
    delete=con.prepareStatement(deleteRfxItem);
    delete.setString(1, orgId);
    delete.setString(2, rfxName);
    delete.setString(3, rfxUniqueId);
    delete.setString(4, revNbr);
    //execute prepared statement
    delete.execute();
    //delete parent - create prepared statment from string
    delete=con.prepareStatement(deleteUniqueRfxHeader);
    delete.setString(1, orgId);
    delete.setString(2, rfxName);
    delete.setString(3, rfxUniqueId);
    delete.setString(4, revNbr);
    delete.execute();
    catch(Exception e){
    deleteFlag=false;
    con.rollback();
    throw e;
    finally {
    try {
    if(deleteFlag==true){
    con.commit();
    System.out.println("Comited");
    con.setAutoCommit(true);
    this.close();
    catch (Exception ex) {}
    return deleteFlag;
    }

    I don't see anything in the posted code that explicitly suggests that a prepared statement is being used more than once.
    More than one prepared statement is being created (and not explicitly closed.) They might or might not produce the same database resource depending on the database/driver or not.
    And from the performance perspective, if and only if, the same database resource is being used then there might be some small performance increase. Although I doubt that it is measurable/significant as a database round trip is probably required for each.

  • Statement vs PreparedStatements which is better in which situation

    Hi i read in a few forums and a few articles that PreparedStatement object performs better than the Statement object in situations where a high number of the same sqls are used because it precompiles the sql statement. such as inserting a 1000 employees into a table.
    i did the following test and found that the gain for using PreparedStatements is sometimes not a gain but a loss.
    What the test basically does is that it inserts an item into the table a 2000 times using both PreparedStatements and Statement objects. And it switches between which object it uses to insert item into the table. So in the end 1000 items would have been inserted using PreparedStatements and 1000 using Statement objects.
    Am i doing somthing wrong with my test or is the so called gain by using PreparedStatements a fluke. Please advise.
    import java.sql.*;
    public class TEST {
        static int Prepcount = 1;
        static long PreptotalTime = 0;
        static long PrepstartTime = 0;
        static long PrependTime = 0;
        static long Prepavarage = 0;
        static int Stmtcount = 1;
        static long StmttotalTime = 0;
        static long StmtstartTime = 0;
        static long StmtendTime = 0;
        static long Stmtavarage = 0;
        static PreparedStatement pst;
        static Statement stmt;
        static ResultSet rs;
        static Connection conn;
        public static void usePrep() {
            try {
                pst = conn.prepareStatement("insert into Dhanu values (?,?)");
                PrepstartTime = System.currentTimeMillis();
                pst.setInt(1, Prepcount);
                pst.setInt(2, Prepcount);
                pst.executeQuery();
                PrependTime = System.currentTimeMillis();
                PreptotalTime = PreptotalTime + (PrependTime - PrepstartTime);
                Prepavarage = PreptotalTime / Prepcount;
                Prepcount++;
                pst.close();
            } catch (Exception e) {
                e.printStackTrace();
        public static void useStatement() {
            try {
                StmtstartTime = System.currentTimeMillis();
                stmt = conn.createStatement();
                rs = stmt.executeQuery("insert into Dhanu values ("+Stmtcount+","+Stmtcount+")");
                StmtendTime = System.currentTimeMillis();
                StmttotalTime = StmttotalTime + (StmtendTime - StmtstartTime);
                Stmtavarage = StmttotalTime / Stmtcount;
                Stmtcount++;
                rs.close();
                stmt.close();
            } catch (Exception e) {
                e.printStackTrace();
        public static void main(String[] args) {
            try {
                Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
                conn = DriverManager.getConnection("jdbc:oracle:thin:@XXX.XXX.XXX.XXX:1521:XXX", "XXX", "XXX");
                System.out.println("Connected to DB");
                conn.setAutoCommit(true);
                for(int x=1;x<=2000;x++){
                    if(x%100==0){
                       System.out.println("Count is "+x);
                    if(x%2==0){
                        usePrep();
                    }else
                        useStatement();
                System.out.println("Prepcount " + Prepcount + " Prepavarage " + Prepavarage + " CurrentExecution " +(PrependTime - PrepstartTime)+ " Totaltime "+PreptotalTime);
                System.out.println("Stmtcount " + Stmtcount + " Stmtavarage " + Stmtavarage+ " CurrentExecution " +(StmtendTime - StmtstartTime)+ " Totaltime "+StmttotalTime);
                System.err.println("Statement time - Prep Time " + (StmttotalTime - PreptotalTime ));
            } catch (Exception ex) {
                ex.printStackTrace();
                System.exit(0);
    }

    sjasja wrote:
    There can still be a performance advantage to PS's even when not used in a loop. Oracle in particular has a textual statement cache. When you execute
    insert into foo values(1);
    insert into foo values(2);
    insert into foo values(3);
    the three statements are textually different, so they get re-parsed and the query optimizer runs thrice. But when you prepare
    insert into foo values(?);
    the parsed and optimized statement remains in the statement cache for some time, and each execution with a different value for "?" can use the pre-parsed statement. The more complex the statement, the bigger the advantage.Yes they do, and so do many others. But it is only that, a cache. It will "usually" be available, not necessarily always. But, in any case, it is still best practice to prepare it, use it multiple times, and close it.
    >
    I have heard rumors of databases (MSSQL???) where a PS is indeed costlier, as the protocol between the JDBC driver and the DB server requires a separate compilation step. One could argue that in this world, where Java is so important in the server side, and the other advantages of PreparedStatement favor its use, any serious database has had much reason in the last decade to implement a protocol where a separate compilation step is not needed, and any other speed penalties for PSs are decidedly not a marketing advantage.One could argue that, and many have, but PreparedStatements did not spring into being with JDBC, they have existed previously. They are easier to use, however, in Java, and some sort or precompilation is required (even if it is only done the first time the statement is actually run) because at some point in time the DB must determine the paths to take when actually executing the statement, and that was the purpose behind precompiled statements in the first place, so that that determination is done once, and used multiple times. Otherwise it is done as the statement is executed, each time a statement is executed (unless, at least in Oracle, the same statement is still in the statement cache, then it is also reused, rather than redetermined).

  • Exception: Call of execute(String) is not allowed for PreparedStatement

    Hi all,
    This query was run fine on SapDB 7.4 from Jave code using prepareStatement()  method:
    declare id11216053819634 cursor for select sc.name, measuredobjectid id from serviceconditions sc, measuredobjects mo where sc.collectionid = mo.collectionid and sc.name like 'DWindowsSLA/%,%,%,%' for reuse
    declare id21216053819634 cursor for select min(sampletime), max(sampletime), name, id11216053819634.id from id11216053819634, d_slastore ss where id11216053819634.id = ss.measuredobjectid and ss.sampletime between '2008-07-14 00:00:00' and '2008-07-14 12:43:35'  group by name, id11216053819634.id for reuse
    select ss.status, ss.statuschange, ss.sampletime, id21216053819634.name from d_slastore ss, id21216053819634 where ss.measuredobjectid = id21216053819634.id and ss.sampletime between '2008-07-14 00:00:00' and '2008-07-14 12:43:35'  and (statuschange != 0 or ss.sampletime = id21216053819634.expression1 or ss.sampletime = id21216053819634.expression2) order by name, sampletime
    We recently upgrade our old SapDb to the latest MaxDB. An now this query produces the error:
    com.sap.dbtech.jdbc.exceptions.JDBCDriverException: SAP DBTech JDBC: Call of execute(String) is not allowed for PreparedStatement.
    Does anyone know how to fix this?
    Thank you very much,
    Irina

    Hi Irina,
    First, welcome to SDN!
    Well, PreparedStatement represents a precompiled SQL statement, so you should be using the no-arg execute() method rather than execute(String).
    HTH!
    \-- Vladimir

  • Bind Variable reuse in GROUP BY queries

    We have several queries that are rather large (in are opinion, that is) and they each have 10 '?' place holders for binding JDBC parameters. These queries also use bind variables in the WHERE and GROUP BY clauses. Eventhough there are 10 bind variable place holders ('?'), there are only 3 distinct values needed.
    So...in TOAD or SQL*Plus, we run the queries and "reuse" the same three bind variables and the query works fine. If we use 10 different bind variables, filled with the 3 values, we get a an error, "not a GROUP BY expression."
    We would like to make these calls as JDBC PreparedStatements and bind the parameters at run time, so that we could take advantage of the statement cache and increase performance. But...since JDBC parameter binding seems to be positional, we seem to be getting 10 different bind variables at runtime in the PreparedStatement call. Is there a way to "reuse" the bind variables that JDBC is binding at runtime?
    Regards,

    Yep...that is what we are doing. We have a work around that is to manually replace the ? with string data and then pass the query in complete. It will work fine for us. I was just checking the alternatives. The query is large, but the offending code is:
    ...( select distinct T3.ptcpt_cd,trunc(new_time(T1.start_dt_gmt, 'GMT', ?)) trade_date,
    sum(decode(T1.sttl_item_num, 10, T1.sttl_item_qnty, 0)) DA_CHARGE_MW,
    sum(decode(T1.sttl_item_num, 10, T1.sttl_item_amt, 0)) DA_CHARGE_AMT,
    sum(decode(T1.sttl_item_num, 30, T1.sttl_item_qnty, 0)) BAL_CHARGE_MW,
    sum(decode(T1.sttl_item_num, 30, T1.sttl_item_amt, 0)) BAL_CHARGE_AMT,
    sum(decode(T1.sttl_item_num, 20, T1.sttl_item_qnty, 0)) DA_CREDIT_MW,
    sum(decode(T1.sttl_item_num, 20, T1.sttl_item_amt, 0)) DA_CREDIT_AMT,
    sum(decode(T1.sttl_item_num, 40, T1.sttl_item_qnty, 0)) BAL_CREDIT_MW,
    sum(decode(T1.sttl_item_num, 40, T1.sttl_item_amt, 0)) BAL_CREDIT_AMT,
    T3.source_cd Source
    from nm_sttl_item_dtl T1, nm_settlement T2, nm_sttl_statement T3
    where trunc(new_time(T1.start_dt_gmt, 'GMT', ?)) between to_date(?,'mm/dd/rrrr') and to_date(?,'mm/dd/rrrr')
    and sttl_item_num in (10, 20, 30, 40)
    and (sttl_item_qnty <> 0 and sttl_item_amt <> 0)
    and T1.sttl_id = T2.sttl_id
    and T2.statement_id = T3.statement_id
    and T3.ptcpt_cd = 'FAC'
    and T3.source_cd = AREA'
    group by T3.ptcpt_cd,trunc(new_time(T1.start_dt_gmt, 'GMT', ?)), T3.source_cd)...

  • Using PreparedStatement and the Oracle Error ORA-1000

    Hi,
    I have a question about PreparedStatement objects that is not so simple to explain for me. What I would like to know is: if I use a PreparedStatement following traditional and generic steps:
    1- PreparedStatement pStmt = Connection.prepareStatement(sQuery);
    2- pStmt.setXXX(i,j);
    n - pStmt.setXXX(i,j);
    n+1 - ResultSet rs = pStmt.executeQuery();
    n+2 - while(rs.next()){ ... retrive ResultSet data  ... }
    n+3 - rs.close()
    n+4 - back to point number 2
    and at the end (as you can see in the point numbered n+4), instead of closing the PreparedStatement pStmt using the close() method, I reuse the PreparedStatement pStmt comeing back to the point numebr 2 and setting again all its parameters with new values ... then ... what heppens in the Oracle database ? Has been the cursor (so the mamory area), associated to my PreparedStatement object pStmt, duplicated or is it the same ?
    I know that Java allows you to do this kind of operations with PreparedStatement, and I know that in tha Java Documentation is explained to follow this strategy to optimize the execution time because in this way the same PreparedStatement is precompiled and prepared only once. But if I do a for loop following the steps explained before, after many iterations I have the error "ORA-1000: maximum open cursors exceeded". This error is the reason of my question. Does this error means that it's mandatory to close a PreparedStatement always, otherwise if you reuse it without closing it then the corresponding database cursor will be duplicated ? If it is so, then I think this is a contradiction with official java documentation ...
    I'm using Oracle8i (version 8.1.7) and Oracle JDBC Thin Driver (Windows NT) for use with JDK 1.2.x. Moreover, in my database istance the parameter "maximum open cursor" is equal to 800 ...
    Thank you very much for suggestions :-)

    There is no need to close a prepared statement or its resultset for every iteration.
    After the first iteration in a loop, all subsequent executions of it will close the previous resultset. By adding close() method, you are making one extra costly call to the DB for no reason.
    Following is the sample code.I know what you are saying. In fact at the beginning I wrote my code in the same way of your sample (see the code of my first post at the begin of this page).
    But doing so, after thousand iterations of the loop, I had "Oracle Error ORA-1000 : maximun open cursor exeeded" even if in my database istance the parameter "maximum open cursor" is equal to 8000.
    At this moment in my code, for each iteration, I close the PreparedStatement and in this way I don't have anymore the error :-((
    So it seems that only in theory we can reuse a preparedStatement without closing it. In fact if we see the oracle system table "$open_cursor" (as Konrad Pietzka suggest me) we can find that, for each interation,
    at our line code "rs = pstmt.executeQuery();" correspond a new cursor in the database: this means that for each method "pstmt.executeQuery()" the database open a new cursor and do not use the previous one as it should.
    I posted a question two months ago to search if someone had the same problem (it seems that Konrad Pietzka had the same situation) and was able to explain me what is the cause.
    The only reason I found by myself for this problem, is that probably the Oracle JDBC Thin Driver for Windows NT/2000 has some bugs... but I'm not sure ...
    Thank you very much for you time !!
    bye :-))
    Fidalma

  • Pooling PreparedStatement s- Connection Pooling in a Servlet-Applicatrion

    We are using OC4J (Servlets) and Oracle9i.
    In the application I use Connection Pooling with
    datasource.xml.
    It works fine.
    Is it possible to create a pool of PreparedStatements and "connect" them with the connections in the pool?
    Has anyone an idea how to do it or an example?
    Thanks in advance
    Peter

    It's not necessarily "bad" as in "it won't work". I personally wouldn't do it because it's poor design. Now, if this is just a small, trivial app. then you have to decide if abstracting things more is worth it. It's not following best practices to put JDBC calls in your servlet. Your servlet should sit there and direct traffic to appropriate handlers, acting as a controller.
    At a minimum I would put the JDBC stuff in its own class and have the servlet use that class.
    Even if you keep your JDBC stuff in your servlet, you really should reuse a common set of DB connections instead of creating a new one each time.

  • Multithreading and PreparedStatement

    I am debugging a problem with the interaction between Hibernate and our JDBC driver.
    Hibernate uses a PreparedStatement to insert values into the database. When it inserts a Timestamp value into the database, it sets the value into the Timestamp object, calls setTimestamp, and then it uses the same Timestamp object in other threads, setting it to different values, before it calls execute on the PreparedStatement.
    My question is, is it valid for an application to assume that the JDBC driver has made a copy of the Timestamp value when it calls setTimestamp, or should it hold off on reusing the Timestamp value until after it has called execute?
    To me it seems that the driver should be able to defer all processing of the PreparedStatement parameters until execute(), because the application could call clearParameters, in which case any work done by the JDBC driver would be wasted. This is not so obvious for Timestamp parameters, but what about stream parameters? Clearly the driver is not going to read the stream until execute.

    I'm not talking about POJO. Think just straight JDBC, inside the guts of Hibernate.
    Here is what Hibernate is doing:
    Timestamp ts = new Timestamp();
    // this one timestamp object is used by multiple threads
    <now we have a thread that does this>
    PreparedStatement pstmt = connection.prepareStatement("some sql");
    ts.setTime(something);
    pstmt.setTimestamp(n, ts);
    <then, another thread does this:>
    PreparedStatement pstmt1 = connection.prepareStatement("some sql");
    ts.setTime(something else);
    pstmt1.setTimestamp(n1, ts);
    <meanwhile, the original thread is doing this>
    pstmt.execute();
    The JDBC driver only keeps a reference to the timestamp when Hibernate calls setTimestamp(). By the time Hibernate calls execute(), another thread has already picked up this timestamp object and reused it, so it doesn't contain the same value that it did when it called setTimestamp().
    It's really horrible when the second thread calls setTime() when the first thread is in the execute() call, in the middle of reading its value to send it to the database, because the first thread reads an inconsistent value from the timstamp object and sends it to the database, which barfs because the inconsistent value ends up being something like Feb. 30. I can get this nightmare to happen pretty regularly on an SMP machine.
    My question is: is Hibernate doing something bad by reusing the Timestamp object before calling execute(), or is the JDBC driver at fault for not keeping a copy of the Timestamp object at setTimestamp() time? I have read the JDBC spec over and over again and I can't see an answer to this question.

  • PreparedStatement and performance..

    <html>
    <b> Q1: Increases Network calls?? </b><br>
    <p> Where there is a table with large number columns , does a bind call to each column from a middle tier makes a network round-trip to the database?? Or does the Oracle JDBC driver cache binds to all columns and send them over in one call?? </p><br>
    <br>
    <b> Q2: Is the Statement faster then PreparedStatement for such large tables??</b><br>
    <p>If the answer to Q1 is yes, Will the recompilation needed by a Statement with values concatenated as literals in the SQL text beat the combined speed of such numerous bind calls ?? </p><br>
    <b> Q3. Recompilation of Statement Vs Oracle SQL Cache </b><br>
    <p> Are Q1 and Q2 moot ?? I.e If different values are concatenated to the Statement SQL text, does that in itself force Oracle to treat it as a different SQL or Has Oracle become advanced enough to treat literals as bind values and hence reuse a Statement cursor with diff. literal values executed in the past in the Cache?? </p><br>
    <br>
    <b> Q4. If Q3 is NO: PreparedStatement VS cached Cursor reuse </b><br>
    <p> If the anwser to Q3 is NO - i.e Statment is inefficient, then can we conclude that PreparedStatement offers double advantages. i.e. within the same session multiple executions are faster , since we only rebind. Also if the connection is closed and PreparedStatement is also closed , but the if same PreparedStatement is reopened in a new Session within the near future, Oracle will reuse the Cached statement, since the SQL text with place-holders('?' marks) definitely matches it. Whereas a Statememt with new literal values concatenated in is a new Statement for every new execution??</p><br>
    <br>
    <b> Q5. Is Q4 moot: PreparedStatement Vs mutiple Sessions </b><br>
    <p> Does closing and reopening a PreparedStatement force a recompilation of the statement anyways, so considerations of a cached Statement reuse is not a benefit for performance tuning here??</p><br>
    Please reply.
    </html>

    Sorry for the formatting messup:
    Q1: Increases Network calls??
    Where there is a table with large number columns , does a bind call to each column from a middle tier makes a network round-trip to the database?? Or does the Oracle JDBC driver cache binds to all columns and send them over in one call??
    Q2: Is the Statement faster then PreparedStatement for such large tables??
    If the answer to Q1 is yes, Will the recompilation needed by a Statement with values concatenated as literals in the SQL text beat the combined speed of such numerous bind calls ??
    Q3. Recompilation of Statement Vs Oracle SQL Cache
    Are Q1 and Q2 moot ?? I.e If different values are concatenated to the Statement SQL text, does that in itself force Oracle to treat it as a different SQL or Has Oracle become advanced enough to treat literals as bind values and hence reuse a Statement cursor with diff. literal values executed in the past in the Cache??
    Q4. If Q3 is NO: PreparedStatement VS cached Cursor reuse
    If the anwser to Q3 is NO - i.e Statment is inefficient, then can we conclude that PreparedStatement offers double advantages. i.e. within the same session multiple executions are faster , since we only rebind. Also if the connection is closed and PreparedStatement is also closed , but the if same PreparedStatement is reopened in a new Session within the near future, Oracle will reuse the Cached statement, since the SQL text with place-holders('?' marks) definitely matches it. Whereas a Statememt with new literal values concatenated in is a new Statement for every new execution??
    Q5. Is Q4 moot: PreparedStatement Vs mutiple Sessions
    Does closing and reopening a PreparedStatement force a recompilation of the statement anyways, so considerations of a cached Statement reuse is not a benefit for performance tuning here??
    Please reply.

  • Performance Problem - MS SQL 2K and PreparedStatement

    Hi all
    I am using MS SQL 2k and used PreparedStatement to retrieve data. There is strange and serious performance problem when the PreparedStatement contains "?" and using PreparedStatement.setX() functions to set its value. I have performed the test with the following code.
    for (int i = 0; i < 10; i ++) {
    try {
    con = DBConnection.getInstance();
    statement = con.prepareStatement("SELECT * FROM cardno WHERE car_no = '" + cardNo + "'");
    // statement = con.prepareStatement("SELECT * FROM cardno WHERE car_no = ?");
    // statement.setString(1, cardNo);
    rs = statement.executeQuery();
    if (rs.next()) {
    catch(SQLException e) {
    e.printStackTrace();
    finally {
    try {
    rs.close();
    statement.close();
    catch(SQLException e) {
    e.printStackTrace();
    Iteration Time (ms)
    1 961
    10 1061
    200 1803
    for (int i = 0; i < 10; i ++) {
    try {
    con = DBConnection.getInstance();
    // statement = con.prepareStatement("SELECT * FROM cardno WHERE car_no = '" + cardNo + "'");
    statement = con.prepareStatement("SELECT * FROM cardno WHERE car_no = ?");
    statement.setString(1, cardNo);
    rs = statement.executeQuery();
    if (rs.next()) {
    catch(SQLException e) {
    e.printStackTrace();
    finally {
    try {
    rs.close();
    statement.close();
    catch(SQLException e) {
    e.printStackTrace();
    Iteration Time (ms)
    1 1171
    10 2754
    100 18817
    200 36443
    The above test is performed with DataDirect JDBC 3.0 driver. The one uses ? and setString functions take much longer to execute, which supposed to be faster because of precompilation of the statement.
    I have tried different drivers - the one provided by MS, data direct and Sprinta JDBC drivers but all suffer the same problem in different extent. So, I am wondering if MS SQL doesn't support for precompiled statement and no matter what JDBC driver I used I am still having the performance problem. If so, many O/R mappings cannot be used because I believe most of them if not all use the precompiled statement.
    Best regards
    Edmond

    Edmond,
    Most JDBC drivers for MS SQL (and I think this includes all the drivers you tested) use sp_executesql to execute PreparedStatements. This is a pretty good solution as the driver doesn't have to keep any information about the PreparedStatement locally, the server takes care of all the precompiling and caching. And if the statement isn't already precompiled, this is also taken care of transparently by SQL Server.
    The problem with this approach is that all names in the query must be fully qualified. This means that the driver has to parse the query you are submitting and make all names fully qualified (by prepending a db name and schema). This is why creating a PreparedStatement takes so much using these drivers (and why it does so every time you create it, even though it's the same PreparedStatement).
    However, the speed advantage of PreparedStatements only becomes visible if you reuse the statement a lot of times.
    As about why the PreparedStatement with no placeholder is much faster, I think is because of internal optimisations (maybe the statement is run as a plain statement (?) ).
    As a conclusion, if you can reuse the same PreparedStatement, then the performance hit is not so high. Just ignore it. However, if the PreparedStatement is created each time and only used a few times, then you might have a performance issue. In this case I would recommend you try out the jTDS driver ( http://jtds.sourceforge.net ), which uses a completely different approach: temporary stored procedures are created for PreparedStatements. This means that no parsing is done by the driver and PreparedStatement caching is possible (i.e. the next time you are preparing the same statement it will take much less as the previously submitted procedure will be reused).
    Alin.

  • PreparedStatement interface

    PreparedStatement objects are compiled and prepared only once by jdbc.
    - The future invocation of the PreparedStatement object does not recompile the SQL statements.
    What does this statement mean ? Does it mean that incase of Statement objects the query gets compiled each time even if there is no change in the query ? Am just trying to understand the difference between Statement and PreparedStatement.

    Note that not all JDBC drivers actually implement the pre-compilation feature of PreparedStatements, but that shouldn't really bother you because that feature is transparent to the developer (i.e. you shouldn't notice if it works or not).
    If it works, it means that the SQL statement is parsed and interpreted only once and stored in some pre-compiled state to be reused on subsequent invocations.
    But in my opinion that is not the most important feature of PreparedStatements. Much more important is the ability to specify values using parameters without having to convert them to the correct SQL string representation. This is the simplest way to protect against [SQL injection attacks|http://en.wikipedia.org/wiki/SQL_injection].

  • Statment used like PreparedStatement

    following is the code of a DAO written by one of the team member. He says that PreparedStatements are slower and so he is writing DAO using Statements. For queries which takes dynamic parameters this code uses a StringUtil class to parse queries and replce all '?' with parameters. I am posting StringUtils class with this code. I request you to send suggestions on this design. I feel this will be slower than using PreparedStatement.
    //Standard JDK imports
    import java.util.Collection;
    import java.util.HashMap;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import com.nate.common.NATEConnection;
    import com.nate.common.exception.DAOException;
    import com.nate.common.exception.NATEConnectionException;
    import com.nate.common.utils.StringUtils;
    import com.nate.web.admin.admusrmgmt.vo.AdminMgmtVO;
    //3rd Party imports
    import org.apache.log4j.Logger;
    public class AdminMgmtDAO
         private NATEConnection m_nateCon;
         private final static String CREATE_ADMIN_QUERY =
              "INSERT INTO ADMIN_USER (USER_ID, "
                   + "USER_ROLE,CREATE_DATE,USE_YN, USER_PHONE,PASSWORD,"
                   + "USER_NAME, HOME_ADDRESS) "
                   + "VALUES (?,'admin',sysdate,?,?,?,?,? )";
         private static final String FIND_ADMIN_BY_ADMINNAME_QUERY =
              "SELECT USE_YN, USER_PHONE, PASSWORD, USER_NAME, "
                   + "HOME_ADDRESS FROM ADMIN_USER WHERE USER_NAME=?";
         /** Logger, used to log messages */
         private Logger m_logger = Logger.getLogger(AdminMgmtDAO.class);
         private final static String LS = System.getProperty("line.separator");
         public AdminMgmtDAO()
              m_nateCon = new NATEConnection();
              m_logger.info("NATE Connection object created");
         public void createAdmin(AdminMgmtVO vo) throws DAOException
              Connection con = null;
              Statement stmt = null;
              try
                   //Example using the StringUtils + Statement classes for CUD operation
                   con = m_nateCon.getConnection();
                   stmt = con.createStatement();
                   StringUtils utils = new StringUtils(CREATE_ADMIN_QUERY);
                   utils.setString(1, vo.getAdminID());
                   utils.setString(2, vo.getStatus());
                   utils.setString(3, vo.getMobileNumber());
                   utils.setString(4, vo.getAdminPassword());
                   utils.setString(5, vo.getAdminName());
                   utils.setString(6, vo.getHomeAddress());
                   String sQuery = StringUtils.getQueryString();
                   if (m_logger.isInfoEnabled())
                        StringBuffer sbBuffer = new StringBuffer(50);
                        sbBuffer.append("Creating Admin user using Query").append(LS);
                        sbBuffer.append(sQuery).append(LS);
                        m_logger.info(sbBuffer.toString());
                   stmt.execute(sQuery);
              catch (NATEConnectionException ex)
                   String strErrMsg =
                        "[Unable to get the Connection from the NATEConnection Class]";
                   m_logger.error(strErrMsg, ex);
                   throw new DAOException(strErrMsg, ex);
              catch (SQLException ex)
                   String strErrMsg = "[Unable to create the Prepared Statment]";
                   m_logger.error(strErrMsg, ex);
                   throw new DAOException(strErrMsg, ex);
              finally
                   try
                        if (stmt != null)
                             stmt.close();
                        if (con != null)
                             con.close();
                   catch (SQLException ex)
                        String strErrMsg = "[Unable to close the Resources]";
                        m_logger.error(strErrMsg, ex);
         } //end of createAdmin
         public Collection findByAdminName(String adminName) throws DAOException
              Connection con = null;
              Statement stmt = null;
              ResultSet rSet = null;
              AdminMgmtVO vo = null;
              Collection result = null; //result sent to client
              //Example using the StringUtils + Statement classes for Read operation
              try
                   con = m_nateCon.getConnection();
                   stmt = con.createStatement();
                   StringUtils utils = new StringUtils(FIND_ADMIN_BY_ADMINNAME_QUERY);
                   utils.setString(1, "%" + adminName + "%");
                   String sQuery = StringUtils.getQueryString();
                   if (m_logger.isInfoEnabled())
                        m_logger.info(
                             "Query performing search :" + sQuery);
                   rSet = pStmt.executeQuery();
                   while (rSet.next())
                        if (result == null)
                             result = new ArrayList();
                        vo = new AdminMgmtVO();
                        vo.setStatus(rSet.getString("USE_YN"));
                        vo.setMobileNumber(rSet.getString("USER_PHONE"));
                        vo.setAdminPassword(rSet.getString("PASSWORD"));
                        vo.setAdminName(rSet.getString("USER_NAME"));
                        vo.setHomeAddress(rSet.getString("HOME_ADDRESS"));
                        result.add(vo);
                        vo = null;
              catch (NATEConnectionException e)
                   String strErrMsg =
                        "[Unable to get the Connection from the NATEConnection Class]";
                   m_logger.error(strErrMsg, e);
                   throw new DAOException(strErrMsg, e);
              catch (SQLException e)
                   String strErrMsg = "[Unable to create the Prepared Statment]";
                   m_logger.error(strErrMsg, e);
                   throw new DAOException(strErrMsg, e);
              finally
                   try
                        if (rSet != null)
                             rSet.close();
                        if (stmt != null)
                             stmt.close();
                        if (con != null)
                             con.close();
                   catch (SQLException e)
                        String strErrMsg = "[Unable to close the Resources]";
                        m_logger.error(strErrMsg, e);
              return result;
         } //end of findByAdminName
    } //end of class
    package com.nate.common.utils;
    import com.nate.common.utils.exception.NotEnoughArgumentsException;
    import com.nate.common.utils.exception.TooManyArgumentsException;
    import java.io.PrintStream;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    public class StringUtils
        public StringUtils(String s)
            m_sQueryStr = s;
            parseString(m_sQueryStr);
            m_argMap = new HashMap();
        public String replaceAll(String s, String s1, String s2)
            String s3 = s;
            Pattern pattern = Pattern.compile(s1);
            Matcher matcher = pattern.matcher(s3);
            return matcher.replaceAll(s2);
        public void setString(int i, String s)
            throws IllegalArgumentException
            if(i > m_map.size())
                throw new IllegalArgumentException();
            int j = s.indexOf("'");
            String s1;
            if(j > 0)
                s1 = replaceAll(s, "'", "''");
            else
                s1 = s;
            m_argMap.put(new Integer(i), s1);
        public void setInt(int i, int j)
            throws IllegalArgumentException
            if(i > m_map.size())
                throw new IllegalArgumentException();
            } else
                m_argMap.put(new Integer(i), String.valueOf(j));
                return;
        public void setLong(int i, int j)
            throws IllegalArgumentException
            if(i > m_map.size())
                throw new IllegalArgumentException();
            } else
                m_argMap.put(new Integer(i), String.valueOf(j));
                return;
        private void parseString(String s)
            int i = 0;
            int j = 0;
            for(i++; i < s.length(); i++)
                char c = s.charAt(i);
                if(c != '?')
                    continue;
                if(m_map == null)
                    m_map = new HashMap();
                m_map.put(new Integer(++j), new Integer(i));
        public void clearParameters()
            m_argMap.clear();
        public StringBuffer getQueryString()
            throws NotEnoughArgumentsException, TooManyArgumentsException
            StringBuffer stringbuffer = new StringBuffer();
            int i = m_map.size();
            int j = m_argMap.size();
            if(j < i)
                throw new NotEnoughArgumentsException();
            if(j > i)
                throw new TooManyArgumentsException();
            int k = 0;
            for(int l = 1; l < i + 1; l++)
                int i1 = ((Integer)m_map.get(new Integer(l))).intValue();
                stringbuffer.append(m_sQueryStr.substring(k, i1));
                stringbuffer.append("'");
                stringbuffer.append(m_argMap.get(new Integer(l)));
                stringbuffer.append("'");
                k = ++i1;
            if(k < m_sQueryStr.length())
                stringbuffer.append(m_sQueryStr.substring(k, m_sQueryStr.length()));
            return stringbuffer;
        public static void main(String args[])
            StringUtils stringutils = new StringUtils("INSERT INTO ADMIN_USER (USER_ID, USER_ROLE,CREATE_DATE,USE_YN, AGE) VALUES (?,'admin',sysdate,?,?)");
            stringutils.setString(1, "test");
            stringutils.setString(2, "Y");
            stringutils.setInt(3, 25);
            System.out.println(stringutils.getQueryString());
            stringutils.clearParameters();
            stringutils.setString(1, "abc'd");
            stringutils.setString(2, "N");
            stringutils.setInt(3, 30);
            System.out.println(stringutils.getQueryString());
            stringutils.setString(1, "%xyz%");
            System.out.println(stringutils.getQueryString());
        private String m_sQueryStr;
        private Map m_map;
        private Map m_argMap;
    }

    As you noticed, the order in which you measure Statement and PreparedStatement matters. This is because all the JDBC driver libraries and standard JDK classes get JIT compiled at the start of the run. The timings are not showing the speed of your code, they are showing the speed of JIT compilation.
    When doing microbenchmarking, run the measured code several times in a loop. The first few loops are likely to be slower as the JIT compiler is running; then timings more or less settle.
    Below is a simple comparision of Statement and PreparedStatement. I won't keep you in suspense: there is no difference under Oracle. "PS's are slow" is a myth.
    Other database servers may differ, so if you are executing lots of small SQL statements in tight time-critical loops, benchmark first, then decide which type of statement to use. (PS's most likely, because you can keep them open and re-use them.)
    If you have big SQL statements, ask yourself: does the difference between a Statement and a PS really matter? If the db server takes a second to execute the query, and the difference is a few milliseconds, wasting time optimizing it is really silly. Especially given the convenience, safety, and portability of not having to do string quoting and date/time formatting yourself.
    // java demo jdbc:oracle:thin:@dbserver:port:dbname username password
    import java.sql.DriverManager;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    public class demo
        static Connection connection;
        static int ROUNDS = 100;
        public static void main(String args[])
         try {
             DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
             connection = DriverManager.getConnection(args[0], args[1], args[2]);
             long best;
             best = -1;
             for (int n = 0; n < 10; n++) {
              long time = staticStatement();
              if (best == -1 || time < best)
                  best = time;
             System.out.println("best time " + best);
             best = -1;
             for (int n = 0; n < 10; n++) {
              long time = staticPrepared();
              if (best == -1 || time < best)
                  best = time;
             System.out.println("best time " + best);
             best = -1;
             for (int n = 0; n < 10; n++) {
              long time = plainStatement();
              if (best == -1 || time < best)
                  best = time;
             System.out.println("best time " + best);
             best = -1;
             for (int n = 0; n < 10; n++) {
              long time = plainPrepared();
              if (best == -1 || time < best)
                  best = time;
             System.out.println("best time " + best);
             best = -1;
             for (int n = 0; n < 10; n++) {
              long time = reuseStatement();
              if (best == -1 || time < best)
                  best = time;
             System.out.println("best time " + best);
             best = -1;
             for (int n = 0; n < 10; n++) {
              long time = reusePrepared();
              if (best == -1 || time < best)
                  best = time;
             System.out.println("best time " + best);
         } catch (Exception e) {
             System.err.println("exception in db test: " + e);
             e.printStackTrace(System.err);
        private static long staticStatement()
         throws SQLException
         long start_time = System.currentTimeMillis();
         for (int n = 0; n < ROUNDS; n++) {
             String sql = "select 42 from dual";
             Statement stmt = connection.createStatement();
             ResultSet res = stmt.executeQuery(sql);
             while (res.next()) {
              int result = res.getInt(1);
             Util.close(res);
             Util.close(stmt);
         long end_time = System.currentTimeMillis();
         long time = end_time - start_time;
         System.out.println("static statement: " + time + " ms");
         return time;
        private static long staticPrepared()
         throws SQLException
         long start_time = System.currentTimeMillis();
         for (int n = 0; n < ROUNDS; n++) {
             String sql = "select 42 from dual";
             PreparedStatement stmt = connection.prepareStatement(sql);
             ResultSet res = stmt.executeQuery();
             while (res.next()) {
              int result = res.getInt(1);
             Util.close(res);
             Util.close(stmt);
         long end_time = System.currentTimeMillis();
         long time = end_time - start_time;
         System.out.println("static prepared: " + time + " ms");
         return time;
        private static long plainStatement()
         throws SQLException
         long start_time = System.currentTimeMillis();
         for (int n = 0; n < ROUNDS; n++) {
             String sql = "select " + n + " from dual";
             Statement stmt = connection.createStatement();
             ResultSet res = stmt.executeQuery(sql);
             while (res.next()) {
              int result = res.getInt(1);
             Util.close(res);
             Util.close(stmt);
         long end_time = System.currentTimeMillis();
         long time = end_time - start_time;
         System.out.println("plain statement: " + time + " ms");
         return time;
        private static long plainPrepared()
         throws SQLException
         long start_time = System.currentTimeMillis();
         for (int n = 0; n < ROUNDS; n++) {
             String sql = "select ? from dual";
             PreparedStatement stmt = connection.prepareStatement(sql);
             stmt.setInt(1, n);
             ResultSet res = stmt.executeQuery();
             while (res.next()) {
              int result = res.getInt(1);
             Util.close(res);
             Util.close(stmt);
         long end_time = System.currentTimeMillis();
         long time = end_time - start_time;
         System.out.println("plain prepared: " + time + " ms");
         return time;
        private static long reuseStatement()
         throws SQLException
         long start_time = System.currentTimeMillis();
         Statement stmt = connection.createStatement();
         for (int n = 0; n < ROUNDS; n++) {
             String sql = "select " + n + " from dual";
             ResultSet res = stmt.executeQuery(sql);
             while (res.next()) {
              int result = res.getInt(1);
             Util.close(res);
         Util.close(stmt);
         long end_time = System.currentTimeMillis();
         long time = end_time - start_time;
         System.out.println("reuse statement: " + time + " ms");
         return time;
        private static long reusePrepared()
         throws SQLException
         long start_time = System.currentTimeMillis();
         String sql = "select ? from dual";
         PreparedStatement stmt = connection.prepareStatement(sql);
         for (int n = 0; n < ROUNDS; n++) {
             stmt.setInt(1, n);
             ResultSet res = stmt.executeQuery();
             while (res.next()) {
              int result = res.getInt(1);
             Util.close(res);
         Util.close(stmt);
         long end_time = System.currentTimeMillis();
         long time = end_time - start_time;
         System.out.println("reuse prepared: " + time + " ms");
         return time;
        public static class Util
         public static void close(Statement s)
             if (s == null)
              return;
             try {
              s.close();
             } catch (Exception e) {
              System.err.println("Util.close: error closing Statement: " + e);
         public static void close(ResultSet s)
             if (s == null)
              return;
             try {
              s.close();
             } catch (Exception e) {
              System.err.println("Util.close: error closing ResultSet: " + e);

  • Statement vs PreparedStatement

    Can anyone offer guidelines ( or point me to documentation) which describes when/why use a
    Statement as opposed to a PreparedStatement.
    I realize that a PreparedStatement can be defined with Bind variables for later substitution and thus the statement gets compiled only once thereby being more efficient.
    But is that the only difference ? does it make sense to use a PreparedStatement even if there are no Bind variables ?

    Whenever you want to re-use a statement you should use Statement and not PreparedStatement.
    Statements can effectively only be used once, since you provide the SQL text to the execute method: this means that when issuing execute (or executeQuery) the statement is always fully reparsed by the database.
    If you have a PreparedStatement object, you can re-execute it, and the database will reuse the parsed statement.

Maybe you are looking for