0

There is a note in all the execute type methods in Statement Interface in the java docs that says

Note:This method cannot be called on a PreparedStatement or CallableStatement.

But why it is So? I mean PreparedStatement is a sub-interface of Statement, then why we can't do so? In fact I tried and it worked.

    ConnectionSetup setCon = new ConnectionSetup();
    // My own class for increasing readability.
    try{

        setCon.loadDriver("com.mysql.jdbc.Driver");//loadDriver calls Class.forName.
        con = setCon.setUpConnection("jdbc:mysql://localhost:3306/odi batsman", "root", "");//setUpConnection asks DriverManager for Connection Object.
        PreparedStatement ps = con.prepareStatement(query);
        ps.execute(query);
    }
    catch(ClassNotFoundException | SQLException e){

        e.printStackTrace();
    }

It worked perfectly fine, the record was entered successfully in the database in spite of the fact that I called execute method (which takes a string as input and inherited from the interface Statement) from PreparedStatement. So whats going on?

EDIT I am just asking that it is written in java docs that we cannot call execute(string) from PreparedStatement but as it is sub-interface of Statement, why we can't?

OldSchool
  • 2,123
  • 4
  • 23
  • 45
  • 1
    If I remember correctly the overloaded version doesn't execute the actual prepared statement with the replaced placeholders. So your query won't work if you have something like this `SELECT * FROM table WHERE blub = ?;`. So you need to use this one: https://docs.oracle.com/javase/7/docs/api/java/sql/PreparedStatement.html#execute%28%29 – Tom Feb 20 '16 at 11:52
  • The duplicate question doesn't ask why you can't use the overloaded version, but the answers will tell you that. – Tom Feb 20 '16 at 11:56
  • About your edit: That part in the JavaDoc doesn't mean that one is unable to call it (the compiler won't moan). You just shouldn't do it, because it doesn't do what you want it to do. – Tom Feb 20 '16 at 12:04
  • @Tom It means query gets executed as if we were using `Statement` object? – OldSchool Feb 20 '16 at 12:05
  • The query gets executed as it is. So `SELECT * FROM table` works, because there is no placeholder in it, but the query in my first comment won't, because the placeholder won't be replaced with an actual value. That's what @dunni tries explain in his (or her) answer. – Tom Feb 20 '16 at 12:08
  • 1
    @Tom Actually, the apidoc says it should throw an `SQLException` in this case, the specific driver implementation - incorrectly - doesn't do that. – Mark Rotteveel Feb 20 '16 at 13:01
  • @MarkRotteveel I wondered why "they" don't override these methods and throw something like a `NotImplementedException`. But since the API requested an exception (which I haven't noticed until now), it is clear that the implementation is wrong. Thanks for the note. – Tom Feb 20 '16 at 13:06

3 Answers3

3

The fact it worked means that the driver implementation you are using (I guess MySQL Connector/J) doesn't comply with the JDBC 4.1 (or higher) specification. The JDBC API javadoc is not only for users of the API, but also describes the behavior that driver vendors need to implement.

The API doc of the various execute(String), executeQuery(String), etc say:

SQLException - if a database access error occurs, this method is called on a closed Statement, the method is called on a PreparedStatement or CallableStatement

This bolded part was added in JDBC 4.1 (Java 7) to clarify the expected behavior.

There are several reasons for this:

  1. Calling one of the execute...(String) methods ignores the prepared statement and so it is probably a bug that you called this method. Raising an exception makes clear that you did something wrong.
  2. Executing a statement string other than the prepared statement on a statement handle, may on some database systems invalidate the prepared statement, leading to unexpected behavior when you first use execute...(String) and subsequently try to execute using execute...() and expecting it to use the earlier prepared statement.

In hindsight it was probably a mistake that Statement, PreparedStatement and CallableStatement form an inheritance hierarchy. For backwards compatibility, this can no longer be changed.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
2

What's going on is, that you basically didn't use the PreparedStatement itself, when you called the execute(String) method, which means, it didn't use the precompiled SQL stuff, which the PreparedStatement does for you. If you would have parameters in your query and you would have set the parameter values in the PreparedStatement, the execute(String) method would ignore these parameters.

dunni
  • 43,386
  • 10
  • 104
  • 99
1

Try to replace:

  ps.execute(query);

With:

   ps.executeQuery();

Because you have already passed the query in PreparedStatement con.prepareStatement(query).

Abdelhak
  • 8,299
  • 4
  • 22
  • 36