home *** CD-ROM | disk | FTP | other *** search
/ PC World 1999 May / PCWorld_1999-05_cd.bin / software / Vyzkuste / inprise / INTRCLNT_15 / DATA.Z / FirstExample.java < prev    next >
Text File  |  1998-09-21  |  22KB  |  451 lines

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