JDBC - HUJI moodle

advertisement
JDBC (@PostgreSQL)
Useful JDBC Links
• Getting Started Guide:
http://java.sun.com/j2se/1.5.0/docs/guide/jdbc/g
etstart/GettingStartedTOC.fm.html
• java.sql Package API:
http://java.sun.com/j2se/1.5.0/docs/api/java/sql/
package-summary.html
2
Why Access a Database from
within a Program?
• Some queries can’t be computed in SQL.
• Why not keep all the data in Java objects?
• “Separation of concerns”: DBMS-s good on
data storage and access; programs
concentrate on algorithms, networking, etc.
3
Java Database Connectivity
• JDBC (Java Database Connectiveity) is an API
(Application Programming Interface),
– That is, a collection of classes and interfaces
• 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
DB
HUJI-CS
4
Hello World Example
import java.sql.*;
public class HelloWorld {
public static void main(String[] str) throws Exception {
Class.forName("org.postgresql.Driver");
Connection con =
DriverManager.getConnection("jdbc:postgresql://dbcourse/public?use
r=me");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select 'hello world'");
while(rs.next()) {
System.out.println(rs.getString(1));
}
stmt.close(); rs.close(); con.close();
}
}
DB
HUJI-CS
5
Packages to Import
• In order to connect to a database from java,
import the following packages:
– java.sql.*;
(usually enough)
– javax.sql.*
(for advanced features, such as
scrollable result sets)
6
DB
HUJI-CS
access
• You will need to add an appropriate jar file
to your classpath. The jar file for the
Postgres driver is available at:
/usr/share/java/postgresql.jar
7
DB
HUJI-CS
Hello World Example
import java.sql.*;
public class HelloWorld {
public static void main(String[] str) throws Exception {
Class.forName("org.postgresql.Driver");
Connection con =
DriverManager.getConnection("jdbc:postgresql://dbcourse/public?u
ser=me");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select 'hello world'");
while(rs.next()) {
System.out.println(rs.getString(1));
}
stmt.close(); rs.close(); con.close();
}
}
DB
HUJI-CS
8
JDBC Architecture
Network
These are
Java classes
Oracle
Driver
Oracle
Java
Application
DB2
Driver
JDBC
DB2
Postgres
Driver
We will
use this one…
Postgres
DB
HUJI-CS
9
JDBC Architecture (cont.)
Application
JDBC
Driver
• Java code calls JDBC library
• JDBC loads a driver
• The driver talks to a particular database
• An application can work with several databases
by using all corresponding drivers
• Ideal: change database engines w/o changing
any application code (not always in practice)
DB
HUJI-CS
10
Seven Steps
• Load the driver
• Define the connection URL
• Establish the connection
• Create a Statement object
• Execute a query using the Statement
• Process the result
• Close the connection
DB
HUJI-CS
11
Registering the Driver
• To use a specific driver, instantiate and
register it within the driver manager:
Driver driver = new
org.postgresql.Driver();
DriverManager.registerDriver(driver);
DB
HUJI-CS
12
A Modular Alternative
• We can register the driver indirectly using
Class.forName("org.postgresql.Driver");
• Class.forName loads the given class dynamically
• When the driver is loaded, it automatically
– creates an instance of itself
– registers this instance within DriverManager
• Hence, the driver class can be given as an
argument of the application
DB
HUJI-CS
13
An Example
// A driver for imaginary1
Class.forName("ORG.img.imgSQL1.imaginary1Driver");
// A driver for imaginary2
Driver driver = new ORG.img.imgSQL2.imaginary2Driver();
DriverManager.registerDriver(driver);
//A driver for PostgreSQL
Class.forName("org.postgresql.Driver");
imaginary1 imaginary2
Postgres
Registered Drivers
DB
HUJI-CS
14
Connecting to the Database
• Every database is identified by a URL
• Given a URL, DriverManager looks for the
driver that can talk to the corresponding
database
• DriverManager tries all registered drivers,
until a suitable one is found
• How is this done?
DB
HUJI-CS
15
Connecting to the Database
Connection con =
DriverManager.getConnection("jdbc:imaginaryDB1");
acceptsURL("jdbc:imaginaryDB1")?
a
r
imaginary1 imaginary2
r
Postgres
Registered Drivers
DB
HUJI-CS
16
The URLs in HUJI-CS
In CS, the URL has the following structure:
jdbc:postgresql://dbcourse/public?user=??
Your login
The machine
running PostgrSQL
You can only access your own account!
DB
HUJI-CS
17
Hello World Example
import java.sql.*;
public class HelloWorld {
public static void main(String[] str) throws Exception {
Class.forName("org.postgresql.Driver");
Connection con =
DriverManager.getConnection("jdbc:postgresql://dbcourse/public?u
ser=me");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select 'hello world'");
while(rs.next()) {
System.out.println(rs.getString(1));
}
stmt.close(); rs.close(); con.close();
}
}
DB
HUJI-CS
18
Hello World Example
import java.sql.*;
public class HelloWorld {
public static void main(String[] str) throws Exception {
Class.forName("org.postgresql.Driver");
Connection con =
DriverManager.getConnection("jdbc:postgresql://dbcourse/public?use
r=me");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select 'hello world'");
while(rs.next()) {
System.out.println(rs.getString(1));
}
stmt.close(); rs.close(); con.close();
}
}
DB
HUJI-CS
19
Interaction with the Database
• We use Statement objects in order to
– Query the db
– Update the db (insert, update, create, drop, …)
• Three different interfaces are used:
Statement, PreparedStatement, CallableStatement
• All are interfaces, hence cannot be instantiated
• They are created by the Connection
DB
HUJI-CS
20
Querying with Statement
String queryStr =
"SELECT * FROM Member " +
"WHERE Lower(Name) = 'harry potter'";
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(queryStr);
executeQuery returns a ResultSet object
representing the query result (discussed later…)
DB
HUJI-CS
21
Changing DB with Statement
String deleteStr =
"DELETE FROM Member " +
"WHERE Lower(Name) = 'harry potter'";
Statement stmt = con.createStatement();
int delnum = stmt.executeUpdate(deleteStr);
• executeUpdate is for data manipulation: insert,
delete, update, create table, etc.
– Anything other than querying!
• executeUpdate returns the number of rows modified
(or 0 for DDL commands)
DB
HUJI-CS
22
About Prepared Statements
• Prepared statements are used for queries that
are executed many times
• Parsed (compiled) by the DBMS only once
• Values of some columns are set after compilation
• Instead of values, use ‘?’ and setType methods
• Hence, prepared statements can be thought of as
statements that contain placeholders to be
substituted later with actual values
DB
HUJI-CS
23
Querying with PreparedStatement
String q =
"SELECT * FROM Items " +
"WHERE Name = ? and Cost < ?";
PreparedStatement pstmt=con.prepareStatement(q);
pstmt.setString(1, "t-shirt");
pstmt.setInt(2, 1000);
ResultSet rs = pstmt.executeQuery();
DB
HUJI-CS
24
Updating with PreparedStatement
String dq =
"DELETE FROM Items " +
"WHERE Name = ? and Cost > ?";
PreparedStatement pstmt = con.prepareStatement(dq);
pstmt.setString(1, "t-shirt");
pstmt.setInt(2, 1000);
int delnum = pstmt.executeUpdate();
DB
HUJI-CS
25
Statement vs. PreparedStatement: Be Careful!
Are these the same? What do they do?
String val = "abc";
PreparedStatement pstmt =
con.prepareStatement("select * from R where A=?");
pstmt.setString(1, val);
ResultSet rs = pstmt.executeQuery();
String val = "abc";
Statement stmt = con.createStatement( );
ResultSet rs =
stmt.executeQuery("select * from R where A=" + val);
DB
HUJI-CS
26
What can be Assigned to “?”
• Will this work?
PreparedStatement pstmt =
con.prepareStatement("select * from ?");
pstmt.setString(1, myFavoriteTableString);
• No!!! “?” can only represent a column
value (to enable pre-compilation)
DB
HUJI-CS
27
PreparedStatement and Security
• Suppose Google was implemented in JDBC
without a PreparedStatement. The main DB query
might have been implemented like this:
Statement s;
s.executeQuery("SELECT URL,Title from Internet " +
"WHERE Content LIKE ‘%" + searchString + "%’");
• What would happen if a hacker searched for:
aaaaa’ UNION SELECT Company AS URL, CreditCardNum
AS Title FROM AdvertisingClients WHERE Company LIKE ‘
DB
HUJI-CS
28
PreparedStatement and Security
• We would get:
Statement s;
s.executeQuery(
"SELECT URL,Title from Internet
WHERE Content LIKE ‘%aaaaa’
UNION
SELECT Company AS URL, CreditCardNum AS Title
FROM AdvertisingClients WHERE Company LIKE ‘%’ ”)
• This technique is known as SQL Injection and is
the main reason for using PreparedStatements
DB
HUJI-CS
29
Some Famous SQL-Injections
• 2009, the United States Justice Department charged an
American citizen Albert Gonzalez and two unnamed
Russians with the theft of 130 million credit card numbers
using an SQL injection attack
•
2010 the British Royal Navy website was compromised
by TinKode using SQL injection.
•
2011, mysql.com, the official homepage for MySQL, was
compromised by TinKode using SQL blind injection
• 2011, "hacktivists" of the group Lulzsec were accused of
using SQLI to steal coupons, download keys, and
passwords that were stored in plaintext on Sony's website,
accessing the personal information of a million users
DB
HUJI-CS
30
Timeout
• Use setQueryTimeOut(int seconds) of Statement
to set a timeout for the driver to wait for a
query to be completed
• If the operation is not completed in the
given time, an SQLException is thrown
• What is it good for?
DB
HUJI-CS
31
Hello World Example
import java.sql.*;
public class HelloWorld {
public static void main(String[] str) throws Exception {
Class.forName("org.postgresql.Driver");
Connection con =
DriverManager.getConnection("jdbc:postgresql://dbcourse/public?use
r=me");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select 'hello world'");
while(rs.next()) {
System.out.println(rs.getString(1));
}
stmt.close(); rs.close(); con.close();
}
}
DB
HUJI-CS
32
ResultSet
• ResultSet objects provide access to the
tables generated as results of executing
Statement queries
• Only one ResultSet per Statement or
PreparedStatement can be open at a given
time!
• The table rows are retrieved in sequence
– A ResultSet maintains a cursor pointing to its
current row
– next() moves the cursor to the next row
DB
HUJI-CS
33
ResultSet Methods
• boolean next()
– Activates the next row
– First call to next() activates the first row
– Returns false if there are no more rows
– Not all of the next calls actually involve the DB
• void close()
– Disposes of the ResultSet
– Allows to re-use the Statement that created it
– Automatically called by most Statement methods
DB
HUJI-CS
34
ResultSet Methods (cont’d)
• Type getType(int columnIndex)
– Returns the given field as the given type
– Indices start at 1 and not 0!
– Add the column name as a comment if it is known!
• Type getType(String columnName)
– Same, but uses name of field
– Less efficient (but may not be your bottleneck anyway)
• Examples: getString(5), getInt(“salary”), getTime(…),
getBoolean(…), ...
• int findColumn(String columnName)
– Looks up column index given column name
DB
HUJI-CS
35
ResultSet Example
Statement stmt = con.createStatement();
ResultSet rs = stmt.
executeQuery("select name,age from Employees");
// Print the result
while(rs.next()) {
System.out.print(rs.getString(1) + ":");
System.out.println(rs.getShort("age"));
}
DB
HUJI-CS
36
Mapping Java Types to SQL Types
SQL Type
CHAR, VARCHAR, LONGVARCHAR
NUMERIC, DECIMAL
BIT
TINYINT
SMALLINT
INTEGER
BIGINT
REAL
FLOAT, DOUBLE
BINARY, VARBINARY, BYTEA
DATE
TIME
TIMESTAMP
DB
HUJI-CS
Java Type
String
java.math.BigDecimal
boolean
byte
short
int
long
float
double
byte[]
java.sql.Date
java.sql.Time
java.sql.Timestamp
37
Null Values
• In SQL, NULL means the field is empty
• Not the same as 0 or “”!
• In JDBC, you must explicitly ask if the lastread field was null
– ResultSet.wasNull(column)
• For example, getInt(column) will return 0 if
the value is either 0 or NULL!
DB
HUJI-CS
38
Null Values
When inserting null values into placeholders
of a PreparedStatement:
– Use setNull(index, Types.sqlType) for primitive types
(e.g. INTEGER, REAL);
– For object types (e.g. STRING, DATE) you may
also use setType(index, null)
DB
HUJI-CS
39
Result-Set Meta-Data
A ResultSetMetaData is an object that can be
used to get information about the properties of
the columns in a ResultSet object
An example: Write the columns of the result set
ResultSetMetaData rsmd = rs.getMetaData();
int numcols = rsmd.getColumnCount();
for (int i = 1 ; i <= numcols; i++)
System.out.print(rsmd.getColumnLabel(i)+" ");
DB
HUJI-CS
40
Database Time
• Java defines three classes to help process time
• java.sql.Date
– year, month, day
• java.sql.Time
– hours, minutes, seconds
• java.sql.Timestamp
– year, month, day, hours, minutes, seconds,
nanoseconds
– Usually use this one
DB
HUJI-CS
41
Hello World Example
import java.sql.*;
public class HelloWorld {
public static void main(String[] str) throws Exception {
Class.forName("org.postgresql.Driver");
Connection con =
DriverManager.getConnection("jdbc:postgresql://dbcourse/public?use
r=me");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select 'hello world'");
while(rs.next()) {
System.out.println(rs.getString(1));
}
stmt.close(); rs.close(); con.close();
}
}
DB
HUJI-CS
42
Cleaning Up After Yourself
Remember: close Connections, Statements,
Prepared Statements and Result Sets
con.close();
stmt.close();
pstmt.close();
rs.close()
DB
HUJI-CS
43
Dealing With Exceptions
An SQLException is actually a list of exceptions
catch (SQLException e) {
while (e != null) {
System.out.println(e.getSQLState());
System.out.println(e.getMessage());
System.out.println(e.getErrorCode());
e = e.getNextException();
}}
DB
HUJI-CS
44
Transaction Management
Transactions and JDBC
• Transaction: more than one statement that must
all succeed (or all fail) together
– e.g., updating several tables due to customer purchase
• Failure− System must reverse all previous actions
• Also can’t leave DB in inconsistent state halfway
through a transaction
• COMMIT = complete transaction
• ROLLBACK = cancel all actions
DB
HUJI-CS
46
An Example
Suppose that 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();
DB
What happens if
this update fails?
HUJI-CS
47
Transaction Lifetime
• Transactions are not opened and closed explicitly
• A transaction starts on 1st (successful) command
– After a connection is established
– After the previous transaction ends
• A transaction ends when COMMIT or ROLLBACK
are applied
– Either explicitly or implicitly (see next 4 slides)
DB
HUJI-CS
48
Committing a Transaction
How do we commit?
• Explicitly invoking Connection.commit()
• Implicitly
– After every query execution, if AutoCommit is true
– When the user normally disconnects (i.e.,
appropriately closes the connection)
– In some DBs: After invoking a DDL command
(CREATE, DROP, RENAME, ALTER, …)
DB
HUJI-CS
49
Automatic Commitment
• A Connection object has a boolean AutoCommit
• If AutoCommit is true (default), then every statement
is automatically committed
• If AutoCommit is false, then each statement is
added to an ongoing transaction
• Change using setAutoCommit(boolean)
• If AutoCommit is false, need to explicitly commit or
rollback the transaction using Connection.commit()
and Connection.rollback()
DB
HUJI-CS
50
Rolling Back
• Rolling Back: Undoing any change to data
within the current transaction
• The ROLLBACK command explicitly rolls
back (and ends) the current transaction
• ROLLBACK is implicitly applied when the
user abnormally disconnects (i.e., without
appropriately closing the connection)
DB
HUJI-CS
51
Fixed Example
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 (SQLException e) { con.rollback(); …; }
DB
HUJI-CS
52
Be Careful
• Suppose we have private functions deposit and
withdraw (doing the expected)
• Would the following function do what we want?
public void transfer (int value, int acc1, int acc2)
try {
deposit(value, acc1);
withdraw(value, acc2);
con.commit();
} catch (SQLException e) { con.rollback(); …; }
DB
HUJI-CS
53
Transaction Isolation
• There is still a lot more to discuss
about transactions:
– How do different transactions interact?
– Does a running transaction see
uncommitted changes?
– Does it see committed changes?
• Details later in the course…
DB
HUJI-CS
54
Download