QOS.ch JIRA

  • Log In Access more options
    • Online Help
    • Keyboard Shortcuts
    • About JIRA
    • JIRA Credits
    • What’s New
  • Dashboards Access more options (Alt+d)
  • Projects Access more options (Alt+p)
  • Issues Access more options (Alt+i)
  • logback-core
  • LBCORE-15

Problems getting autogenerated Keys in Oracle with Oracle JDBC 10.2.03

  • Log In
  • Views
    • XML
    • Word
    • Printable

Details

  • Type: Bug Bug
  • Status: Resolved Resolved
  • Priority: Blocker Blocker
  • Resolution: Fixed
  • Affects Version/s: unspecified
  • Fix Version/s: 0.9.10
  • Component/s: Appender
  • Labels:
    None
  • Environment:
    Operating System: Windows
    Platform: PC
  • Bugzilla Id:
    57

Description

I've encountered troubles logging StackTrace/MDC entries with die DBAppender on our plattform! We are using Oracle 9.2.0.6.0 on a Solaris Box with Oracle JDBC Driver 10.2.0.3!

I've debugged the processing of LogMessages into DBAppenderBase.append()!

There I found a call "con.prepareStatement(getInsertSQL())" which is followed by a call "subAppend(...)"

As far as I understand Oracle Drivers return generatedKeys only, if you use the right prepareStatement() methods, which is in my understanding the following:

PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
                                   throws SQLException
@see http://java.sun.com/j2se/1.5.0/docs/api/java/sql/Connection.html#prepareStatement(java.lang.String,%20int)
which is available since JDK 1.4

Activity

Ascending order - Click to sort in descending order
  • All
  • Comments
  • History
  • Activity
Hide
Permalink
Sébastien Pennec added a comment - 30/Mar/07 3:10 PM
Hello Klaus,

I've checked your problem, I guess that we could change the call to the prepareStatement() method. But before we change it, We have to test it against other databases.

Dev notes:
The test case of DBAppender uses HSQLDB. That database's driver does not support the call to prepareStatement(String sqlQuery, int getGeneratedKeys)[1].

It looks like MySQL supports that call.

[1]http://hsqldb.org/doc/src/org/hsqldb/jdbc/jdbcConnection.html#prepareStatement(java.lang.String,%20int)
Show
Sébastien Pennec added a comment - 30/Mar/07 3:10 PM Hello Klaus, I've checked your problem, I guess that we could change the call to the prepareStatement() method. But before we change it, We have to test it against other databases. Dev notes: The test case of DBAppender uses HSQLDB. That database's driver does not support the call to prepareStatement(String sqlQuery, int getGeneratedKeys)[1]. It looks like MySQL supports that call. [1]http://hsqldb.org/doc/src/org/hsqldb/jdbc/jdbcConnection.html#prepareStatement(java.lang.String,%20int)
Hide
Permalink
Klaus Unger added a comment - 26/Jun/07 4:42 PM
Hello Sébastien,

any news on this topic, as we are desperately waiting for a fix/solution

many thanks in advance.

kind regards
K:)
Show
Klaus Unger added a comment - 26/Jun/07 4:42 PM Hello Sébastien, any news on this topic, as we are desperately waiting for a fix/solution many thanks in advance. kind regards K:)
Hide
Permalink
John Gibson added a comment - 11/Jan/08 5:16 AM
I think that we can fix this problem by making different prepareStatement() calls in DBAppenderBase depending upon the value of cnxSupportsGetGeneratedKeys.
For example, this seemed to fix the problem for me with Oracle 10:

PreparedStatement insertStatement;
if(cnxSupportsGetGeneratedKeys) {
  insertStatement = connection
      .prepareStatement(getInsertSQL(), new String[] { "EVENT_ID" } );
} else {
  insertStatement = connection
      .prepareStatement(getInsertSQL());
}
Show
John Gibson added a comment - 11/Jan/08 5:16 AM I think that we can fix this problem by making different prepareStatement() calls in DBAppenderBase depending upon the value of cnxSupportsGetGeneratedKeys. For example, this seemed to fix the problem for me with Oracle 10: PreparedStatement insertStatement; if(cnxSupportsGetGeneratedKeys) {   insertStatement = connection       .prepareStatement(getInsertSQL(), new String[] { "EVENT_ID" } ); } else {   insertStatement = connection       .prepareStatement(getInsertSQL()); }
Hide
Permalink
Søren Boisen added a comment - 15/Oct/08 4:03 PM
It's important to note that the original suggestion, to use prepareStatement(String, int) will not work. In this case Oracle will return the ROWID of the inserted row instead of the EVENT_ID column. As John Gibson wrote, prepareStatement(String, String[]) should be used instead, specifying EVENT_ID as the name of the column to be returned.

For other people that cannot wait for this bug to be fixed, a workaround is to write your own class extending DBAppender:

public class OracleDBAppender extends DBAppender {

    @Override
    public void append (LoggingEvent eventObject) {
        Connection connection = null;
        try {
            connection = connectionSource.getConnection();
            connection.setAutoCommit(false);

            PreparedStatement insertStatement = connection.prepareStatement(
                    getInsertSQL(), new String[] {"EVENT_ID"});

            subAppend(eventObject, connection, insertStatement);

            // we no longer need the insertStatement
            if (insertStatement != null) {
                insertStatement.close();
                insertStatement = null;
            }

            connection.commit();
        } catch (Throwable sqle) {
            addError("problem appending event", sqle);
        } finally {
            DBHelper.closeConnection(connection);
        }
    }
}

Then in your configuration file simply declare the class of the appender to attach as your new OracleDBAppender class.
Show
Søren Boisen added a comment - 15/Oct/08 4:03 PM It's important to note that the original suggestion, to use prepareStatement(String, int) will not work. In this case Oracle will return the ROWID of the inserted row instead of the EVENT_ID column. As John Gibson wrote, prepareStatement(String, String[]) should be used instead, specifying EVENT_ID as the name of the column to be returned. For other people that cannot wait for this bug to be fixed, a workaround is to write your own class extending DBAppender: public class OracleDBAppender extends DBAppender {     @Override     public void append (LoggingEvent eventObject) {         Connection connection = null;         try {             connection = connectionSource.getConnection();             connection.setAutoCommit(false);             PreparedStatement insertStatement = connection.prepareStatement(                     getInsertSQL(), new String[] {"EVENT_ID"});             subAppend(eventObject, connection, insertStatement);             // we no longer need the insertStatement             if (insertStatement != null) {                 insertStatement.close();                 insertStatement = null;             }             connection.commit();         } catch (Throwable sqle) {             addError("problem appending event", sqle);         } finally {             DBHelper.closeConnection(connection);         }     } } Then in your configuration file simply declare the class of the appender to attach as your new OracleDBAppender class.
Hide
Permalink
Ceki Gulcu added a comment - 21/Oct/08 11:51 PM
I have tested the existing code on Oracle 11g (version 11.1.0.6.0) and it seems to work just fine.
I'll see if I can reproduce it with Oracle 10g.
Show
Ceki Gulcu added a comment - 21/Oct/08 11:51 PM I have tested the existing code on Oracle 11g (version 11.1.0.6.0) and it seems to work just fine. I'll see if I can reproduce it with Oracle 10g.
Hide
Permalink
Ceki Gulcu added a comment - 22/Oct/08 11:00 PM - edited
It's actually more of a JDBC driver issue then a RDBMS version
issue. I could reproduce the problem on Oracle 10g using ojdbc14.jar
(version 10.2.0.1). This JDBC drivers support the getGeneratedKeys
method. The problem cannot be reproduced with an older driver,
classic12.jar, version 9.0.1.4.0, because it does not support
getGeneratedKeys().

Anyway, the code has been modified to use the
connection. prepareStatement() method taking two arguments, the sql
statement follows by the auto-generated columnNames, as suggested John
Gibson. Surprisingly enough, this change is compatible with other
databases supporting getGeneratedKeys().

Fixed in revision 1860
Show
Ceki Gulcu added a comment - 22/Oct/08 11:00 PM - edited It's actually more of a JDBC driver issue then a RDBMS version issue. I could reproduce the problem on Oracle 10g using ojdbc14.jar (version 10.2.0.1). This JDBC drivers support the getGeneratedKeys method. The problem cannot be reproduced with an older driver, classic12.jar, version 9.0.1.4.0, because it does not support getGeneratedKeys(). Anyway, the code has been modified to use the connection. prepareStatement() method taking two arguments, the sql statement follows by the auto-generated columnNames, as suggested John Gibson. Surprisingly enough, this change is compatible with other databases supporting getGeneratedKeys(). Fixed in revision 1860

People

  • Assignee:
    Logback dev list
    Reporter:
    Klaus Unger
Vote (0)
Watch (2)

Dates

  • Created:
    30/Mar/07 1:51 PM
    Updated:
    22/Oct/08 11:00 PM
    Resolved:
    22/Oct/08 11:00 PM
  • Atlassian JIRA (v5.0.4#731-sha1:3aa7374)
  • Report a problem
  • Powered by a free Atlassian JIRA open source license for logback. Try JIRA - bug tracking software for your team.