CS 580 Client-Server Spring Semester, 2004 JDBC |
||
---|---|---|
© 2004, All Rights Reserved, SDSU & Roger Whitney San Diego State University -- This page last updated 10-Feb-04 |
SQL and Java
Some Jargon
SQL Access Group (SAG) - multivendor "Standards" group
SQL Call Level Interface (CLI)
Microsoft's Open Database Connectivity (ODBC)
JDBC
Java Database Connectivity
Sun states
JDBC 2.1 Core
Standard part of JDK 1.2
JDBC drivers must implement JDBC 2.x before you can use it
MySQL driver for JDBC 2.x is in pre-beta release
Additional Features
JDBC 2.0 Package
Now java.sql
Once was optional Java package javax.sql
JDBC 3.0
java.sql & javax.sql in JDK 1.4
Most advanced features are in javax.sql
JDBC Architecture
JDBC driver provides connections to database via drivers
JDBC Drivers, JDBC Versions & Java API
java.sql.* is mainly interfaces for JDBC Drivers
The driver for the database determines the actual functionality
Sample JDBC Use
import java.sql.*; public class SampleConnection { public static void main (String args[]) throws Exception { String dbUrl = "jdbc:mysql://rugby.sdsu.edu:8777/test"; String user = "whitney"; String password = "mylittleSecret"; System.out.println("Load Driver!"); Class.forName("com.mysql.jdbc.Driver"); Connection rugby; rugby = DriverManager.getConnection( dbUrl, user, password); Statement getTables = rugby.createStatement(); ResultSet tableList = getTables.executeQuery("SELECT * FROM name"); while (tableList.next() ) System.out.println("Last Name: " + tableList.getString(1) + '\t' + "First Name: " + tableList.getString( "first_name")); rugby.close(); } }
DownLoading the MySQl JDBC Driver
http://www.mysql.com/downloads/api-jdbc-stable.html
Contains the jar file mysql-connector-java-3.0.10-stable-bin.jar
Needs to be in your classpath
Implements JDBC 3.0, but some of the advance features are not functional
See the documentation at:
http://www.mysql.com/documentation/connector-j/index.html
Using JDBC
Step 1. Load the driver(s)
Step 2. Connect to the database
Step 3. Issue queries and receive results
Loading a Driver
The most commonly used way
A well-written JDBC driver is loaded using Class.forName
To load the Oracle driver
import java.sql.*; class JdbcTest { public static void main (String args []) throws ClassNotFoundException { Class.forName ("oracle.jdbc.OracleDriver"); } }
This requires that oracle package be in your path
A properly written driver will register itself with the DriverManager class
Loading a Driver
The Recommended Way
Use the command line to specify the driver
java –Djdbc.drivers=org.postgresql.Driver yourProgramName
Makes it easier to change database vendors with out recompiling the code
Long command lines need script to run
JDBC Drivers
Java supports four types of JDBC drivers
- JDBC-ODBC bridge plus ODBC driver
JDBC URL Structure
jdbc:<subprotocol>:<subname>
<subprotocol>
jdbc:odbc:<data-source-name>[;<attribute-name>=<attribute-value>]*
jdbc:odbc:qeor7 jdbc:odbc:wombat jdbc:odbc:wombat;CacheSize=20;ExtensionCase=LOWER jdbc:odbc:qeora;UID=kgh;PWD=fooey
PostgreSQL Subprotocol
jdbc:postgresql:database jdbc:postgresql://host/database jdbc:postgresql://host:port/database
MySQL Subprotocol
jdbc:mysql://[host][,failoverhost...][:port]/[database] [?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]...
hostname defaults to 127.0.0.1
port defaults to 3306
Legal values for properties can be found at:
http://www.mysql.com/documentation/connector-j/index.html#id2800782
DriverManager.getConnection - Using JDBC URL
Three forms:
getConnection(URL, Properties) getConnection(URL, userName, Password) getConnection(URLWithUsernamePassword)
Form 1
static String ARS_URL = "jdbc:oracle:@PutDatabaseNameHere"; DriverManager.getConnection(ARS_URL, "whitney","secret");Form 2
DriverManager.getConnection( "jdbc:oracle:whitney/secret@PutDatabaseNameHere");Form 3
java.util.Properties info = new java.util.Properties(); info.addProperty ("user", "whitney"); info.addProperty ("password","secret"); DriverManager getConnection (ARS_URL ,info );
java.sql.DriverManager
Driver related methods
Print a message to the current JDBC log stream
DataSource
The current recommended way to get a connection is using a DataSource
In theory DataSource supports connection pooling
DataSources are optional in JDBC 2.0
MySql DataSource is a wrapper for DriverManager
Queries
Connection toFargo = DriverManager.getConnection(database, user, password); Statement namesTable = toFargo.createStatement(); ResultSet namesFound = namesTable.executeQuery("SELECT * FROM name");
executeUpdate
ExecuteUpdate Example
public static void main (String args[]) throws Exception { String dbUrl = "jdbc:mysql://rugby.sdsu.edu:8777/test"; String user = "whitney"; String password = "SCECmysql"; System.out.println("Load Driver!"); Class.forName("com.mysql.jdbc.Driver"); Connection rugby; rugby = DriverManager.getConnection( dbUrl, user, password); Statement getTables = rugby.createStatement(); int rowsModified = getTables.executeUpdate("UPDATE name SET first_name = 'foo' WHERE last_name='Whitney'"); System.out.println( "Number of rows modified: " + rowsModified); rugby.close(); }
getObject
A replacement for the getXXX methods
Rather than
ResultSet tableList = getTables.executeQuery("SELECT * FROM name"); String firstName = tableList.getString( 1);
Can use
ResultSet tableList = getTables.executeQuery("SELECT * FROM name"); String firstName = (String) tableList.getObject( 1);
getObject( int k) returns the object in the k’th column of the current row
getObject( String columnName) returns the object in the named column
SQL Data Types and Java
SQL type |
Java type |
CHAR |
String |
VARCHAR |
String
|
LONGVARCHAR |
String |
NUMERIC |
java.math.BigDecimal |
DECIMAL |
java.math.BigDecimal |
BIT |
boolean |
TINYINT |
byte |
SMALLINT |
short |
INTEGER |
int |
BIGINT |
long |
REAL |
float |
FLOAT |
double |
DOUBLE |
double |
BINARY |
byte[] |
VARBINARY |
byte[] |
LONGVARBINARY |
byte[] |
DATE |
java.sql.Date |
TIME |
java.sql.Time |
TIMESTAMP |
java.sql.Timestamp |
Some Result Set Issues
What happens when we call next() too many times?
What happens if we try to access data before we call next?
In both cases an java.sql.SQLException is thrown
Mixing ResultSets
Can't have two active result sets on same statement
Statement namesTable = toFargo.createStatement(); Connection rugby; rugby = DriverManager.getConnection( dbUrl, user, password); Statement getTables = rugby.createStatement(); ResultSet count = getTables.executeQuery("SELECT COUNT(*) FROM name"); ResultSet tableList = getTables.executeQuery("SELECT * FROM name"); while (tableList.next() ) System.out.println("Last Name: " + tableList.getObject(1) + '\t' + "First Name: " + tableList.getObject( "first_name")); // Raises java.sql.SQLException count.getObject(1); rugby.close();
this can happen two threads have access to the same statement
Two Statements on one Connection work
Connection rugby; rugby = DriverManager.getConnection( dbUrl, user, password); Statement getTables = rugby.createStatement(); Statement tableSize = rugby.createStatement(); ResultSet count = getTables.executeQuery("SELECT COUNT(*) FROM name"); ResultSet tableList = tableSize.executeQuery("SELECT * FROM name"); while (tableList.next() ) System.out.println("Last Name: " + tableList.getObject(1) + '\t' + "First Name: " + tableList.getObject( "first_name")); count.next(); System.out.println("Count: " + count.getObject(1) ); count.close(); tableList.close(); rugby.close();
Threads & Connections
Some JDBC drivers are not thread safe
Transactions
A transaction consists of one or more statements that have been executed and completed
A transaction ends when a commit or rollback is sent
Connections are opened in auto commit mode:
Transaction Example
import java.sql.*; public static void main (String args[]) throws Exception { String dbUrl = "jdbc:mysql://rugby.sdsu.edu:8777/test"; String user = "whitney"; String password = "SCECmysql"; System.out.println("Load Driver!"); Class.forName("com.mysql.jdbc.Driver"); Connection rugby; rugby = DriverManager.getConnection( dbUrl, user, password); rugby.setAutoCommit(false); Statement update = rugby.createStatement(); update.executeUpdate("INSERT INTO name (first_name, last_name) VALUES ( 'Donald', 'Duck') "); update.executeUpdate("INSERT INTO name (first_name, last_name) VALUES ( 'Micky', 'Mouse') "); rugby.rollback(); update.close(); Statement getTables = rugby.createStatement(); ResultSet tableList = getTables.executeQuery("SELECT * FROM name"); while (tableList.next() ) System.out.println("Last Name: " + tableList.getObject(1) + '\t' + "First Name: " + tableList.getObject( "first_name")); rugby.close(); }
MySql & Transactions
Note that MySql does not support transactions unless it is a recent version and is configured to do so.
There is a test to see if the database supports transactions
However, it did return the incorrect answer when I tested the code
Connection rugby; rugby = DriverManager.getConnection( dbUrl, user, password); rugby.setAutoCommit(false); boolean hasTransactions = ((com.mysql.jdbc.Connection)rugby).supportsTransactions(); System.out.println( "Supports transctions? " + hasTransactions);
PreparedStatement
PreparedStatement objects contain SQL statements that have been sent to the database to be prepared for execution
The SQL statements contains variables (IN parameters) which are given values before statement is executed
Only makes sense to use if database and driver keeps statements open after they have been committed
IN parameters are indicated by a ?
Values are set by position
String flightOut = "SELECT * FROM AirlineSchedule WHERE from = ?";
PreparedStatement Example
import java.sql.*; import java.io.*; Connection rugby; rugby = DriverManager.getConnection( dbUrl, user, password); String findPerson = "SELECT * FROM name WHERE last_name = ?"; PreparedStatement find = rugby.prepareStatement( findPerson ); find.setObject( 1, "whitney" ); ResultSet person = find.executeQuery(); while (person.next() ) System.out.println("Last Name: " + person.getObject(1) + '\t' + "First Name: " + person.getObject( "first_name")); find.clearParameters(); find.setObject( 1, "olson" ); person = find.executeQuery(); while (person.next() ) System.out.println("Last Name: " + person.getObject(1) + '\t' + "First Name: " + person.getObject( "first_name")); rugby.close();
Works in MySql
Batch Updates
Allows one to send a batch of updates in one request
Connection rugby; rugby = DriverManager.getConnection( dbUrl, user, password); Statement batch = rugby.createStatement(); batch.addBatch("INSERT INTO name (first_name, last_name) VALUES ('Lion', 'King')"); batch.addBatch("INSERT INTO name (first_name, last_name) VALUES ('Little', 'Nemo')"); int[] updates = batch.executeBatch(); for( int k = 0; k < updates.length;k++) System.out.println( "Update " + k + " rows affected " + updates[k]); rugby.close();
CallableStatement
Some databases have stored procedures (a procedure of SQL statements)
CallableStatement allows a Java program to invoke a stored procedure in a database
DatabaseMetaData
The class DatabaseMetaData allows you to obtain information about the database
The 113 methods in DatabaseMetaData give you more information than you thought possible
Copyright ©, All rights reserved.
2004 SDSU & Roger Whitney, 5500 Campanile Drive, San Diego, CA 92182-7700 USA.
OpenContent license defines the copyright on this document.
Previous    visitors since 10-Feb-04    Next