1
• JDBC is used for accessing databases from Java applications
• Information is transferred from relations to objects and vice-versa
– databases optimized for searching/indexing
– objects optimized for engineering/flexibility
2
• When executing an SQL statement via
JDBC, it is not checked for errors until it is run (Not checked during compilation)
3
• There are queries that can not be computed in SQL:
– Given a table Bus(Source, Destination) find all pairs of places that it is possible to travel between (paths of any length)
• Java allows for a convenient user interface to the database
4
• Load the driver
• Establish the Connection
• Create a Statement object
• Execute a query
• Process the result
• Close the connection
5
• In order to connect to the Oracle database from java, import the following packages:
– java.sql.*; (usually enough)
– javax.sql.* (for advanced features, such as scrollable result sets)
6
Driver
Manager
Application Driver
• The application creates a driver instance and registers it with the DriverManager.
• The DriverManager connects a driver to the DB
• The DriverManager keeps track of registered driver instances and their connections to DB’s.
• The Driver “talks” to a particular database through the connection
Driver
Manager
Application
Driver
1. Initializing a driver: new oracle.jdbc.driver.OracleDriver()
2. Registering it with the DriverManager:
DriverManager.registerDriver(…)
3. Getting a connection:
DriverManager.getConnection(URL)
Note:
• Stages 1+2 may be combined with
Class.forName(“oracle.jdbc.driver.OracleDriver");
• In Stage 3, the Manager tries all drivers and assigns a connection to the first driver that succeeds.
8
String path = "jdbc:oracle:thin:";
String host = "sol4";
String port = "1521";
String db = "stud";
String login = “gidi";
String password = “password”;
String url = path + login + "/" + password +
"@" + host +":" + port + ":" + db;
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection con = DriverManager.getConnection(url);
9
1. Statement createStatement()
– returns a new Statement object
“prepared” because it already includes the query string
2. PreparedStatement prepareStatement(String sql)
– returns a new PreparedStatement object
• Both are used to send SQL commands to the DB
• Both are created by the connection
• Statements are used for queries that are only issued once.
• A statement can activate:
1.
executeQuery(String query) : for queries that don’t change the DB (select)
2.
executeUpdate(String query) : for queries which affect the DB (create, delete, drop, etc.)
11
String queryStr =
"SELECT * FROM Sailors " +
"WHERE Name = 'joe smith'";
No semicolon(;) !!!
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(queryStr);
• The executeQuery method returns a ResultSet object representing the query result.
12
String deleteStr =
“DELETE FROM Sailors " +
"WHERE sid = 15";
Statement stmt = con.createStatement(); int delnum = stmt.executeUpdate(deleteStr);
No semicolon(;) !!!
• executeUpdate returns the number of rows modified.
13
• Suppose we would like to run the query
SELECT * FROM Emp where name=‘moshe’;
• But we would like to run this for all employees
(separately), not only moshe…
• Could we create a variable instead of ‘moshe’ which would get a different name every time??..
14
• Prepared Statements are used for queries that are executed many times with possibly different contents.
• A PreparedStatement object includes the query and is prepared for execution.
• Question marks can be inserted as variables.
-setString(i, value)
-setInt(i, value)
The i-th question mark is set to the given value.
15
String queryStr =
"SELECT * FROM Sailors " +
"WHERE Name = ? and Rating < ?”;
PreparedStatement pstmt = con.prepareStatement(queryStr); pstmt.setString(1, “Joe”); pstmt.setInt(2, 8);
Value to insert
1 st question mark
ResultSet rs = pstmt.
executeQuery ();
16
String deleteStr =
“DELETE FROM Boats " +
"WHERE Name = ? and Color = ?”;
PreparedStatement pstmt = con.prepareStatement(deleteStr); pstmt.setString(1, “Fluffy”); pstmt.setString(2, "red"); int delnum = pstmt.
executeUpdate ();
17
• Are these the same? What do they do?
String val = “Joe”;
PreparedStatement pstmt = con.prepareStatement(“select * from Sailors where sname=?”); pstmt.setString(1, val);
ResultSet rs = pstmt.executeQuery();
String val = “Joe”;
Statement stmt = con.createStatement( );
ResultSet rs = stmt.executeQuery(“select * from
Sailors where sname=” + val);
18
• Will this always work?
Statement stmt = con.createStatement( );
ResultSet rs = stmt.executeQuery(“select * from R where A =‘ ” + val + “ ’ ”);
• The moral: When getting input from the user, always use a PreparedStatement
19
• Will this work?
PreparedStatement pstmt = con.prepareStatement(“select * from ?”); pstmt.setString(1, "Sailors");
No! will attempt to insert ‘sailors’, and result in:
Select * from ‘sailors’
We can put ? only instead of values
20
Statement
ExecuteQuery(String Q)
ResultSet createStatement()
Statement
Connection
ExecuteUpdate(String Q) int
Prepared
Statement setString(int num,String val)
ExecuteQuery() prepareStatement
(String Q)
Prepared
Statement
Connection
ExecuteUpdate()
ResultSet int
21
• A ResultSet is an object which contains the result of a query- a “table”.
• Only one ResultSet per Statement can be open at once(!).
• A ResultSet maintains a cursor pointing to its current row of data.
• The ' next ' method moves the cursor to the next row
• As of JDBC 2.0, scrollable ResultSets are available, which also include ‘ previous ’, ’ first ’,
‘ last ’, etc..
• Any methods on the resultSet will occur on the current row.
• The cursor is positioned before the first row upon creation.
Statement stmt=con.createStatement();
ResultSet rs = stmt.executeQuery
("SELECT * FROM Table1"); while (rs.next()) {
//something…
}
• Getting the value in some column (for the current row):
– getString(int columnNum);
String s = rs.getString(“column1");
– getString(String columnName);
– getInt(int columnNum);
– getInt(String columnName);
– Etc…
• To check if null was returned, you have to use wasNull() on the ResultSet after getting the value.
• The driver maps SQL types (varchar, number,…) to the appropriate Java method (getString, getInt…)
24
SQL type
Java method
25
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM
Table1");
// retrieve and print the values for the current row while (rs.next()) { int i = rs.getInt("a");
String s = rs.getString("b"); float f = rs.getFloat("c");
System.out.println("ROW = " + i + " " + s + " " + f);
}
26
1. TYPE_FORWARD_ONLY: The default, simple RS.
2. TYPE_SCROLL_INSENSITIVE : Scrollable RS, does not modify when the DB is modified
3. TYPE_SCROLL_SENSITIVE : Scrollable RS, if its values are changed in the DB, they will also change in the RS.
In addition, a ResultSet may be either:
1. CONCUR_READ_ONLY: the programmer cannot change the ResultSet (default)
2. CONCUR_UPDATABLE: the programmer can change the ResultSet
27
For Statement:
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery( "SELECT * from emp");
For PreparedStatement:
PreparedStatement pstmt= con.prepareStatement("SELECT * FROM Emp where Eid=?” ,
ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE); pstmt.setInt(1, "1000010");
ResultSet rs = stmt.executeQuery();
28
An object created by the ResultSet which holds information about its columns
ResultSetMetaData rsmd = rs.getMetaData(); int numcols = rsmd.getColumnCount();
} for (int i = 1 ; i <= numcols; i++) { if (i > 1) System.out.print(",");
System.out.print(rsmd.getColumnLabel(i));
29
} while (rs.next()) { for (int i = 1 ; i <= numcols; i++) { if (i > 1) System.out.print(",");
System.out.print(rs.getString(i));
}
System.out.println("");
30
• Remember to close the Connections,
Statements, PreparedStatements and
ResultSets
Highly recommended con.close(); stmt.close(); pstmt.close(); rs.close();
Recommended
Optional (Will otherwise be closed by its calling statement)
31
• An exception may be chained: catch (SQLException e) { while (e != null) {
//human readable message about the exception
System.out.println(e.getMessage());
//String describing the reason of the exception
System.out.println(e.getSQLState());
} }
//driver-dependant code for the exception
System.out.println(e.getErrorCode()); e = e.getNextException();
32
String table1=“create table table1(col1 integer, col2 integer)”;
Statement st=con.createStatement(); int resCreate=st.executeUpdate(table1);
PreparedStatement ps1 = con.prepareStatement(“insert into Table1 values(?,?)”); for(int i=0;i<10;i++){ ps1.setInt(1,i); ps1.setInt(2,i*i); ps1.executeUpdate();
}
Statement st2=con.createStatement();
ResultSet rs=executeQuery(“select col2 from Table1”); while(rs.next()){
System.out.println(rs.getInt(1)); }
33
• You can use Stmnt.setQueryTimeOut(int secs) to set a timeout for the driver to wait for a statement to be completed
• If the operation is not completed in the given time, an SQLException is thrown
34
35
• Transaction = 2 or more statements which must all succeed (or all fail) together
• If one fails, the system must reverse all previous actions
• Also can’t leave DB in inconsistent state halfway through a transaction
• COMMIT = complete transaction
• ROLLBACK = abort
36
• Suppose we want to transfer money from bank account 13 to account 72:
PreparedStatement pstmt = con.prepareStatement(“update BankAccount set amount = amount + ?
where accountId = ?”); pstmt.setInt(1,-100); pstmt.setInt(2, 13); pstmt.executeUpdate(); pstmt.setInt(1, 100); pstmt.setInt(2, 72); pstmt.executeUpdate();
What happens if this update fails?
37
• The connection has a state called AutoCommit mode
• if AutoCommit is true, then every statement is automatically committed
• if AutoCommit is false, then every statement is added to an ongoing transaction
• Default: true
38
con.setAutoCommit(boolean val)
• If you set AutoCommit to false, you must explicitly commit or rollback the transaction using Connection.commit() and
Connection.rollback()
39
con.setAutoCommit(false); try {
PreparedStatement pstmt = con.prepareStatement(“update BankAccount set amount = amount + ?
where accountId = ?”); pstmt.setInt(1,-100); pstmt.setInt(2, 13); pstmt.executeUpdate();
} pstmt.setInt(1, 100); pstmt.setInt(2, 72); pstmt.executeUpdate(); con.commit(); catch (Exception e) { con.rollback();
40
• Useful link regarding JDBC: http://java.sun.com/j2se/1.3/docs/guide/jdbc/ getstart/GettingStartedTOC.fm.html
41