home *** CD-ROM | disk | FTP | other *** search
/ Enter 1999 September / ENTER9_2.bin / prog_8 / jbuilder3 / TRIAL / INTRCLNT / DATA.Z / DriverExample.java < prev    next >
Encoding:
Java Source  |  1999-01-18  |  19.5 KB  |  413 lines

  1. // Copyright InterBase Software Corporation, 1998.
  2. // Written by com.inprise.interbase.interclient.r&d.PaulOstler :-)
  3. //
  4. // A small application to demonstrate basic, but not necessarily simple, JDBC features.
  5. //
  6. // Note: you will need to hardwire the path to your copy of employee.gdb
  7. //       as well as supply a user/password in the code below at the
  8. //       beginning of method main().
  9.  
  10. public class DriverExample
  11. {
  12.   // Make a connection to an employee.gdb on your local machine,
  13.   // and demonstrate basic JDBC features.
  14.   // Notice that main() uses its own local variables rather than
  15.   // static class variables, so it need not be synchronized.
  16.   public static void main (String args[])
  17.   {
  18.     // Modify the following hardwired settings for your environment.
  19.     // Note: localhost is a TCP/IP keyword which resolves to your local machine's IP address.
  20.     //       If localhost is not recognized, try using your local machine's name or
  21.     //       the loopback IP address 127.0.0.1 in place of localhost.
  22.     String databaseURL = "jdbc:interbase://localhost/d:/databases/employee.gdb";
  23.     String user = "sysdba";
  24.     String password = "masterkey";
  25.     String driverName = "interbase.interclient.Driver";
  26.  
  27.     // As an exercise to the reader, add some code which extracts databaseURL,
  28.     // user, and password from the program args[] to main().
  29.     // As a further exercise, allow the driver name to be passed as well,
  30.     // and modify the code below to use driverName rather than the hardwired
  31.     // string "interbase.interclient.Driver" so that this code becomes
  32.     // driver independent.  However, the code will still rely on the
  33.     // predefined table structure of employee.gdb.
  34.  
  35.     // See comment about closing JDBC objects at the end of this main() method.
  36.     System.runFinalizersOnExit (true);
  37.  
  38.     // Here are the JDBC objects we're going to work with.
  39.     // We're defining them outside the scope of the try block because
  40.     // they need to be visible in a finally clause which will be used
  41.     // to close everything when we are done.
  42.     // The finally clause will be executed even if an exception occurs.
  43.     java.sql.Driver d = null;
  44.     java.sql.Connection c = null;
  45.     java.sql.Statement s = null;
  46.     java.sql.ResultSet rs = null;
  47.  
  48.     // Any return from this try block will first execute the finally clause
  49.     // towards the bottom of this file.
  50.     try {
  51.  
  52.       // Let's try to register the InterClient JDBC driver with the driver manager
  53.       // using one of various registration alternatives...
  54.       int registrationAlternative = 1;
  55.       switch (registrationAlternative) {
  56.  
  57.       case 1:
  58.         // This is the standard alternative and simply loads the driver class.
  59.         // Class.forName() instructs the java class loader to load
  60.         // and initialize a class.  As part of the class initialization
  61.         // any static clauses associated with the class are executed.
  62.         // Every driver class is required by the jdbc specification to automatically
  63.         // create an instance of itself and register that instance with the driver
  64.         // manager when the driver class is loaded by the java class loader
  65.         // (this is done via a static clause associated with the driver class).
  66.         //
  67.         // Notice that the driver name could have been supplied dynamically,
  68.         // so that an application is not hardwired to any particular driver
  69.         // as would be the case if a driver constructor were used, eg.
  70.         // new interbase.interclient.Driver().
  71.         try {
  72.           Class.forName ("interbase.interclient.Driver");
  73.         }
  74.         catch (java.lang.ClassNotFoundException e) {
  75.           // A call to Class.forName() forces us to consider this exception :-)...
  76.           System.out.println ("InterClient not found in class path");
  77.           System.out.println (e.getMessage ());
  78.           return;
  79.         }
  80.         break;
  81.  
  82.       case 2:
  83.         // There is a bug in some JDK 1.1 implementations, eg. with Microsoft
  84.         // Internet Explorer, such that the implicit driver instance created during
  85.         // class initialization does not get registered when the driver is loaded
  86.         // with Class.forName().
  87.         // See the FAQ at http://java.sun.com/jdbc for more info on this problem.
  88.         // Notice that in the following workaround for this bug, that if the bug
  89.         // is not present, then two instances of the driver will be registered
  90.         // with the driver manager, the implicit instance created by the driver
  91.         // class's static clause and the one created explicitly with newInstance().
  92.         // This alternative should not be used except to workaround a JDK 1.1
  93.         // implementation bug.
  94.         try {
  95.           java.sql.DriverManager.registerDriver (
  96.              (java.sql.Driver) Class.forName ("interbase.interclient.Driver").newInstance ()
  97.           );
  98.         }
  99.         catch (java.lang.ClassNotFoundException e) {
  100.           // A call to Class.forName() forces us to consider this exception :-)...
  101.           System.out.println ("Driver not found in class path");
  102.           System.out.println (e.getMessage ());
  103.           return;
  104.         }
  105.         catch (java.lang.IllegalAccessException e) {
  106.           // A call to newInstance() forces us to consider this exception :-)...
  107.           System.out.println ("Unable to access driver constructor, this shouldn't happen!");
  108.           System.out.println (e.getMessage ());
  109.           return;
  110.         }
  111.         catch (java.lang.InstantiationException e) {
  112.           // A call to newInstance() forces us to consider this exception :-)...
  113.           // Attempt to instantiate an interface or abstract class.
  114.           System.out.println ("Unable to create an instance of driver class, this shouldn't happen!");
  115.           System.out.println (e.getMessage ());
  116.           return;
  117.         }
  118.         catch (java.sql.SQLException e) {
  119.           // A call to registerDriver() forces us to consider this exception :-)...
  120.           System.out.println ("Driver manager failed to register driver");
  121.           showSQLException (e);
  122.           return;
  123.         }
  124.         break;
  125.  
  126.       case 3:
  127.         // Add the InterClient driver name to your system's jdbc.drivers property list.
  128.         // The driver manager will load drivers from this system property list.
  129.         // System.getProperties() may not be allowed for applets in some browsers.
  130.         // For applets, use one of the Class.forName() alternatives above.
  131.         java.util.Properties sysProps = System.getProperties ();
  132.         StringBuffer drivers = new StringBuffer ("interbase.interclient.Driver");
  133.         String oldDrivers = sysProps.getProperty ("jdbc.drivers");
  134.         if (oldDrivers != null)
  135.           drivers.append (":" + oldDrivers);
  136.         sysProps.put ("jdbc.drivers", drivers.toString ());
  137.         System.setProperties (sysProps);
  138.         break;
  139.  
  140.       case 4:
  141.         // Advanced: This is a non-standard alternative, and is tied to
  142.         // a particular driver implementation, but is very flexible.
  143.         //
  144.         // It may be possible to configure a driver explicitly, either thru
  145.         // the use of non-standard driver constructors, or non-standard
  146.         // driver "set" methods which somehow tailor the driver to behave
  147.         // differently from the default driver instance.
  148.         // Under this alternative, a driver instance is created explicitly
  149.         // using a driver specific constructor.  The driver may then be
  150.         // tailored differently from the default driver instance which is
  151.         // created automatically when the driver class is loaded by the java class loader.
  152.         // For example, perhaps a driver instance could be created which
  153.         // is to behave like some older version of the driver.
  154.         //
  155.         // d = new interbase.interclient.Driver ();
  156.         // d.setVersion (interbase.interclient.Driver.OLD_VERSION);
  157.         // DriverManager.registerDriver (d);
  158.         // c = DriverManager.getConnection (...);
  159.         //
  160.         // Since two drivers, with differing behavior, are now registered with
  161.         // the driver manager, they presumably must recognize different jdbc
  162.         // subprotocols.  For example, the tailored driver may only recognize
  163.         // "jdbc:interbase:old_version://...", whereas the default driver instance
  164.         // would recognize the standard "jdbc:interbase://...".
  165.         // There are currently no methods, such as the hypothetical setVersion(),
  166.         // for tailoring an InterClient driver so this 4th alternative is academic
  167.         // and not necessary for InterClient.
  168.         //
  169.         // It is also possible to create a tailored driver instance which
  170.         // is *not* registered with the driver manager as follows
  171.         //
  172.         // d = new interbase.interclient.Driver ();
  173.         // d.setVersion (interbase.interclient.Driver.OLD_VERSION);
  174.         // c = d.connect (...);
  175.         //
  176.         // this is the most usual case as this does not require differing
  177.         // jdbc subprotocols since the connection is obtained thru the driver
  178.         // directly rather than thru the driver manager.
  179.         d = new interbase.interclient.Driver ();
  180.       }
  181.  
  182.       // At this point the driver should be registered with the driver manager.
  183.       // Try to find the registered driver that recognizes interbase URLs...
  184.       try {
  185.         // We pass the entire database URL, but we could just pass "jdbc:interbase:"
  186.         d = java.sql.DriverManager.getDriver (databaseURL);
  187.         System.out.println ("InterClient version " +
  188.                             d.getMajorVersion () +
  189.                             "." +
  190.                             d.getMinorVersion () +
  191.                             " registered with driver manager.");
  192.       }
  193.       catch (java.sql.SQLException e) {
  194.         System.out.println ("Unable to find InterClient among the registered drivers.");
  195.         showSQLException (e);
  196.         return;
  197.       }
  198.  
  199.       // Advanced info: Class.forName() loads the java class for the driver.
  200.       // All JDBC drivers are required to have a static clause that automatically
  201.       // creates an instance of themselves and registers that instance
  202.       // with the driver manager.  So there is no need to call
  203.       // DriverManager.registerDriver() explicitly unless the driver allows
  204.       // for tailored driver instances to be created (each instance recognizing
  205.       // a different jdbc sub-protocol).
  206.  
  207.       // Now that InterClient is registered with the driver manager,
  208.       // try to get a connection to an employee.gdb database on this local machine
  209.       // using one of two alternatives for obtaining connections...
  210.       int connectionAlternative = 1;
  211.       switch (connectionAlternative) {
  212.  
  213.       case 1:
  214.         // This alternative is driver independent;
  215.         // the driver manager will find the right driver for you based on the jdbc subprotocol.
  216.         // In the past, this alternative did not work with applets in some browsers because of a
  217.         // bug in the driver manager.  I believe this has been fixed in the jdk 1.1 implementations.
  218.         try {
  219.           c = java.sql.DriverManager.getConnection (databaseURL, user, password);
  220.           System.out.println ("Connection established.");
  221.         }
  222.         catch (java.sql.SQLException e) {
  223.           System.out.println ("Unable to establish a connection through the driver manager.");
  224.           showSQLException (e);
  225.           return;
  226.         }
  227.         break;
  228.         
  229.       case 2:
  230.         // If you're working with a particular driver d, which may or may not be registered,
  231.         // you can get a connection directly from it, bypassing the driver manager...
  232.         try {
  233.           java.util.Properties connectionProperties = new java.util.Properties ();
  234.           connectionProperties.put ("user", user);
  235.           connectionProperties.put ("password", password);
  236.           c = d.connect (databaseURL, connectionProperties);
  237.           System.out.println ("Connection established.");
  238.         }
  239.         catch (java.sql.SQLException e) {
  240.           System.out.println ("Unable to establish a connection through the driver.");
  241.           showSQLException (e);
  242.           return;
  243.         }
  244.         break;
  245.       }
  246.  
  247.       // Let's disable the default autocommit so we can undo our changes later...
  248.       try {
  249.         c.setAutoCommit (false);
  250.         System.out.println ("Auto-commit is disabled.");
  251.       }
  252.       catch (java.sql.SQLException e) {
  253.         System.out.println ("Unable to disable autocommit.");
  254.         showSQLException (e);
  255.         return;
  256.       }
  257.  
  258.       // Now that we have a connection, let's try to get some meta data...
  259.       try {
  260.         java.sql.DatabaseMetaData dbMetaData = c.getMetaData ();
  261.        
  262.         // Ok, let's query a driver/database capability
  263.         if (dbMetaData.supportsTransactions ())
  264.           System.out.println ("Transactions are supported.");
  265.         else
  266.           System.out.println ("Transactions are not supported.");
  267.  
  268.         // What are the views defined on this database?
  269.         java.sql.ResultSet tables = dbMetaData.getTables (null, null, "%", new String[] {"VIEW"});
  270.         while (tables.next ()) {
  271.           System.out.println (tables.getString ("TABLE_NAME") + " is a view.");
  272.         }
  273.         tables.close ();
  274.       }
  275.       catch (java.sql.SQLException e) {
  276.         System.out.println ("Unable to extract database meta data.");
  277.         showSQLException (e);
  278.         // What the heck, who needs meta data anyway ;-(, let's continue on...
  279.       }
  280.  
  281.       // Let's try to submit some static SQL on the connection.
  282.       // Note: This SQL should throw an exception on employee.gdb because
  283.       //       of an integrity constraint violation.  
  284.       try {
  285.         s = c.createStatement ();
  286.         s.executeUpdate ("update employee set salary = salary + 10000");
  287.       }
  288.       catch (java.sql.SQLException e) {
  289.         System.out.println ("Unable to increase everyone's salary.");
  290.         showSQLException (e);
  291.         // We expected this to fail, so don't return, let's keep going...
  292.       }
  293.  
  294.       // Let's submit some static SQL which produces a result set.
  295.       // Notice that the statement s is reused with a new SQL string.
  296.       try {
  297.         rs = s.executeQuery ("select full_name from employee where salary < 50000");
  298.       }
  299.       catch (java.sql.SQLException e) {
  300.         System.out.println ("Unable to submit a static SQL query.");
  301.         showSQLException (e);
  302.         // We can't go much further without a result set, return...
  303.         return;
  304.       }
  305.  
  306.       // The query above could just as easily have been dynamic SQL,
  307.       // eg. if the SQL had been entered as user input.
  308.       // As a dynamic query, we'd need to query the result set meta data
  309.       // for information about the result set's columns.
  310.       try {
  311.         java.sql.ResultSetMetaData rsMetaData = rs.getMetaData ();
  312.         System.out.println ("The query executed has " +
  313.                             rsMetaData.getColumnCount () +
  314.                             " result columns.");
  315.         System.out.println ("Here are the columns: ");
  316.         for (int i = 1; i <= rsMetaData.getColumnCount (); i++) {
  317.           System.out.println (rsMetaData.getColumnName (i) +
  318.                               " of type " +
  319.                               rsMetaData.getColumnTypeName (i));
  320.         }
  321.       }
  322.       catch (java.sql.SQLException e) {
  323.         System.out.println ("Unable to extract result set meta data.");
  324.         showSQLException (e);
  325.         // What the heck, who needs meta data anyway ;-(, let's continue on...
  326.       }
  327.  
  328.       // Ok, lets step thru the results of the query...
  329.       try {
  330.         System.out.println ("Here are the employee's whose salary < $50,000");
  331.         while (rs.next ()) {
  332.           System.out.println (rs.getString ("full_name"));
  333.         }
  334.       }
  335.       catch (java.sql.SQLException e) {
  336.         System.out.println ("Unable to step thru results of query");
  337.         showSQLException (e);
  338.         return;
  339.       }
  340.  
  341.       // As an exercise to the reader, rewrite this code so that required
  342.       // table structures are created dynamically using executeUpdate() on DDL.
  343.       // In this way the code will be able to run against any database file rather
  344.       // than just a previously setup employee.gdb.
  345.       // Just to get you started, you'll want to define a method something like
  346.       // the following...
  347.       //
  348.       // private static void createTableStructures (java.sql.Connection c) throws java.sql.SQLException
  349.       // {
  350.       //   // Some drivers don't force commit on DDL, InterClient does,
  351.       //   // see DatabaseMetaData.dataDefinitionCausesTransactionCommit().
  352.       //   // This is not necessary for InterClient, but may be for other drivers...
  353.       //   c.setAutoCommit (true);
  354.       //
  355.       //   java.sql.Statement s = c.createStatement();
  356.       //
  357.       //   // Drop table EMPLOYEE if it already exists, if not that's ok too.
  358.       //   try { s.executeUpdate ("drop table EMPLOYEE"); } catch (java.sql.SQLException e) {}
  359.       //
  360.       //   // Ok, now that we're sure the table isn't already there, create it...
  361.       //   s.executeUpdate ("create table EMPLOYEE (...)");
  362.       //
  363.       //   // Ok, now populate the EMPLOYEE table...
  364.       //   s.executeUpdate ("insert into EMPLOYEE values (...)");
  365.       //
  366.       //   s.close();
  367.       //   c.setAutoCommit (false);
  368.       // }
  369.       //
  370.       // As a further exercise, rewrite the code so that the database itself
  371.       // is created dynamically using Server.createDatabase(), further reducing
  372.       // setup requirements.  However, this will only work with InterClient/InterBase
  373.       // since Server.createDatabase() is not a JDBC method.
  374.     }
  375.  
  376.     // This finally clause will be executed even if "return" was called in case of any exceptions above.
  377.     finally {
  378.       System.out.println ("Closing database resources and rolling back any changes we made to the database.");
  379.  
  380.       // Now that we're all finished, let's release database resources.
  381.       try { if (rs!=null) rs.close (); } catch (java.sql.SQLException e) { showSQLException (e); }
  382.       try { if (s!=null) s.close (); } catch (java.sql.SQLException e) { showSQLException (e); }
  383.  
  384.       // Before we close the connection, let's rollback any changes we may have made.
  385.       try { if (c!=null) c.rollback (); } catch (java.sql.SQLException e) { showSQLException (e); }
  386.       try { if (c!=null) c.close (); } catch (java.sql.SQLException e) { showSQLException (e); }
  387.  
  388.      // If you don't close your database objects explicitly as above,
  389.      // they may be closed by the object's finalizer, but there's
  390.      // no guarantee if or when the finalizer will be called.
  391.      // In general, object finalizers are not called on program exit.
  392.      // It's recommended to close your JDBC objects explictly,
  393.      // but you can use System.runFinalizersOnExit(true), as at the beginning
  394.      // of this method main(), to force finalizers to be called before
  395.      // program exit.
  396.     }
  397.   }
  398.  
  399.   // Display an SQLException which has occured in this application.
  400.   private static void showSQLException (java.sql.SQLException e)
  401.   {
  402.     // Notice that a SQLException is actually a chain of SQLExceptions,
  403.     // let's not forget to print all of them...
  404.     java.sql.SQLException next = e;
  405.     while (next != null) {
  406.       System.out.println (next.getMessage ());
  407.       System.out.println ("Error Code: " + next.getErrorCode ());
  408.       System.out.println ("SQL State: " + next.getSQLState ());
  409.       next = next.getNextException ();
  410.     }
  411.   }
  412. }
  413.