ORA-29977:在保证模式

时间:2016-01-30 20:10:07

标签: java spring oracle

我正在尝试从我的java类中执行DatabaseChangeListener,我收到以下错误:

  

ORA-29977:用于查询注册的不支持的列类型   保证模式。

我需要一个实现,只要表中插入了新行,我就会收到通知。

这是我尝试的代码,用于将更改通知给java:

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.Properties;

import oracle.jdbc.OracleConnection;
import oracle.jdbc.OracleDriver;
import oracle.jdbc.OracleStatement;
import oracle.jdbc.dcn.DatabaseChangeEvent;
import oracle.jdbc.dcn.DatabaseChangeListener;
import oracle.jdbc.dcn.DatabaseChangeRegistration;

public class DBChangeNotification
{
  static final String USERNAME= "artl";
  static final String PASSWORD= "artl";
  static String URL="jdbc:oracle:thin:@localhost:1521:orclaq";

  public static void main(String[] argv)
  {
    /*if(argv.length < 1)
    {
      System.out.println("Error: You need to provide the URL in the first argument.");


      System.exit(1);
    }*/
   // URL = argv[0];
    DBChangeNotification demo = new DBChangeNotification();
    try
    {
      demo.run();
    }
    catch(SQLException mainSQLException )
    {
      mainSQLException.printStackTrace();
    }
  }

  void run() throws SQLException
  {
    OracleConnection conn = connect();

    // first step: create a registration on the server:
    Properties prop = new Properties();

    // if connected through the VPN, you need to provide the TCP address of the client.
    // For example:
    // prop.setProperty(OracleConnection.NTF_LOCAL_HOST,"14.14.13.12");

    // Ask the server to send the ROWIDs as part of the DCN events (small performance
    // cost):
    prop.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS,"true");
// 
//Set the DCN_QUERY_CHANGE_NOTIFICATION option for query registration with finer granularity.
 prop.setProperty(OracleConnection.DCN_QUERY_CHANGE_NOTIFICATION,"true");
 //prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_VSESSION_OSUSER,"artl");
 //prop.setProperty(OracleConnection.CONNECTION_PROPERTY_PASSWORD,"artl");

    // The following operation does a roundtrip to the database to create a new
    // registration for DCN. It sends the client address (ip address and port) that
    // the server will use to connect to the client and send the notification
    // when necessary. Note that for now the registration is empty (we haven't registered
    // any table). This also opens a new thread in the drivers. This thread will be
    // dedicated to DCN (accept connection to the server and dispatch the events to 
    // the listeners).
    DatabaseChangeRegistration dcr = conn.registerDatabaseChangeNotification(prop);

    try
    {
        System.out.println("try");
      // add the listenerr:
      DCNDemoListener list = new DCNDemoListener(this);
      dcr.addListener(list);

      // second step: add objects in the registration:
      Statement stmt = conn.createStatement();
      // associate the statement with the registration:
      ((OracleStatement)stmt).setDatabaseChangeRegistration(dcr);
      ResultSet rs = stmt.executeQuery("select * from act_code_metadata where product_id=1159");
      System.out.println("rs.next() "+rs.next());
      while (rs.next())
      {}
      String[] tableNames = dcr.getTables();
      System.out.println("tableNames "+tableNames);
      for(int i=0;i<tableNames.length;i++)
        System.out.println(tableNames[i]+" is part of the registration.");
      rs.close();
      stmt.close();
    }
    catch(SQLException ex)
    {
         System.out.println("Exception here 3");
      // if an exception occurs, we need to close the registration in order
      // to interrupt the thread otherwise it will be hanging around.
      if(conn != null)
        conn.unregisterDatabaseChangeNotification(dcr);
      throw ex;
    }
    finally
    {
      try
      {
        // Note that we close the connection!
        conn.close();
      }
      catch(Exception innerex){ innerex.printStackTrace(); 
      System.out.println("Exception here 4");
      }
    }

    synchronized( this ) 
    {
      // The following code modifies the dept table and commits:
      try
      {
          Date date=new Date();
        OracleConnection conn2 = connect();
        conn2.setAutoCommit(false);
        Statement stmt2 = conn2.createStatement();
        stmt2.executeUpdate("insert into act_code_metadata (ACT_CODE,PRODUCT_ID,ACT_ACTION,ACT_EXECUTION_ORDER,REQUEST_STRC_ID,CREATION_DATE,LAST_UPDATE_DATE) values ('ACT_CODE_1151',1151,'cool dept',1,1,"+date+","+date+")",
Statement.RETURN_GENERATED_KEYS);
        ResultSet autoGeneratedKey = stmt2.getGeneratedKeys();
        if(autoGeneratedKey.next())
          System.out.println("inserted one row with ROWID="+autoGeneratedKey.getString(1));      
        stmt2.executeUpdate("insert into act_code_metadata (ACT_CODE,PRODUCT_ID,ACT_ACTION,ACT_EXECUTION_ORDER,REQUEST_STRC_ID,CREATION_DATE,LAST_UPDATE_DATE) values ('ACT_CODE_1151',1151,'cool dept',1,1,"+date+","+date+")",

Statement.RETURN_GENERATED_KEYS);
        autoGeneratedKey = stmt2.getGeneratedKeys();
        if(autoGeneratedKey.next())
          System.out.println("inserted one row with ROWID="+autoGeneratedKey.getString(1));
        stmt2.close();
        conn2.commit();
        conn2.close();
      }
      catch(SQLException ex) { ex.printStackTrace();
      System.out.println("Exception here 1");
      }

      // wait until we get the event
      try{ this.wait();} catch( InterruptedException ie ) {
          System.out.println("Exception here 2");
      }
    }

    // At the end: close the registration (comment out these 3 lines in order
    // to leave the registration open).
    OracleConnection conn3 = connect();
    conn3.unregisterDatabaseChangeNotification(dcr);
    conn3.close();
  }

  /**
   * Creates a connection the database.
   */
  OracleConnection connect() throws SQLException
  {
    OracleDriver dr = new OracleDriver();
    Properties prop = new Properties();
    prop.setProperty("user",DBChangeNotification.USERNAME);
    prop.setProperty("password",DBChangeNotification.PASSWORD);
    return (OracleConnection)dr.connect(DBChangeNotification.URL,prop);
  }
}
/**
 * DCN listener: it prints out the event details in stdout.
 */
class DCNDemoListener implements DatabaseChangeListener
{
  DBChangeNotification demo;
  DCNDemoListener(DBChangeNotification dem)
  {
    demo = dem;
  }
  public void onDatabaseChangeNotification(DatabaseChangeEvent e)
  {
    Thread t = Thread.currentThread();
    System.out.println("DCNDemoListener: got an event ("+this+" running on thread "+t+")");
    System.out.println(e.toString());
    synchronized( demo ){ demo.notify();}
  }
}

请建议我如何解决此问题。提前谢谢。

3 个答案:

答案 0 :(得分:2)

你的问题在这里:

  Statement stmt = conn.createStatement();
  // associate the statement with the registration:
  ((OracleStatement)stmt).setDatabaseChangeRegistration(dcr);
 ResultSet rs = stmt.executeQuery("select * from act_code_metadata where      product_id=1159");
  System.out.println("rs.next() "+rs.next());
  while (rs.next())
  {}

错误告诉您DCN注册中的列类型不受支持。也许是一个blob或clob。由于我看不到您的表格结构,请编辑查询并选择 - 建立 - 一次一列。无论如何,您没有对结果集列进行任何操作,因此应该很容易找到它。

答案 1 :(得分:1)

自您使用SELECT * FROM格式后发生此错误,而您应在此处使用SELECT column_name(s) FROM格式。

答案 2 :(得分:1)

您可以将以下属性设置为尽力模式

prop.setProperty(OracleConnection.DCN_BEST_EFFORT,"true");