Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Serializability wikipedia , lookup
Entity–attribute–value model wikipedia , lookup
Extensible Storage Engine wikipedia , lookup
Concurrency control wikipedia , lookup
Microsoft Jet Database Engine wikipedia , lookup
Clusterpoint wikipedia , lookup
Database model wikipedia , lookup
Microsoft SQL Server wikipedia , lookup
Versant Object Database wikipedia , lookup
Relational model wikipedia , lookup
Oracle Database wikipedia , lookup
Introduction to JDBC Programming Oracle Korea 발표순서 Basic JDBC Programming Advanced Programming JDBC 2.0 Features SQLJ Q&A Basic JDBC Programming Basic JDBC Programming After completing this lesson, you should be able to do the following: – Connect to a database using Java Database Connectivity (JDBC) – Create and execute a query using JDBC – Invoke prepared statements – Commit and roll back transactions – Use the Oracle JDBC extensions to improve performance JDBC JDBC is a standard interface for connecting to relational databases from Java. The JDBC classes and interfaces are in the java.sql package. JDBC 1.22 is part of JDK 1.1; JDBC 2.0 is part of Java 2 Overview of Querying a Database With JDBC Connect Query Process results Close Stage 1: Connect Connect Register the driver Query Connect to the database Process results Close A JDBC Driver Is an interpreter that translates JDBC method calls to vendor-specific database commands Database commands JDBC calls Driver Database Implements interfaces in java.sql Can also provide a vendor’s extensions to the JDBC standard Oracle JDBC Driver Oracle 8i JDBC “Thin” driver Java Socket JDBC “OCI” driver SQL*Net SQL*Net OCI C Lib Java Store Procedure SQL & PL/SQL Engines JDBC “Thin” driver (also available in server) JDBC “OCI” driver Java Engine JDBC “ServerSide Internal” driver database Lib JDBC “Server-Side Internal” driver (Kernal PRogram Bundled Calls driver) Oracle JDBC Drivers Thin driver – a 100% Java driver for client-side use without an Oracle installation, particularly with applets OCI drivers (OCI8 and OCI7) – for client-side use with an Oracle client installation server-side Thin driver – which is functionally the same as the client-side Thin driver, but is for code that runs inside an Oracle server and needs to access a remote server, including middletier scenarios server-side internal driver – for code that runs inside the target server Oracle JDBC Drivers: Thin Client Driver Written entirely in Java Applets must use this driver Applet JDBC Thin driver O7 or O8 Client Server Oracle JDBC Drivers: OCI Client Drivers Written in C and Java Must be installed on the client Application JDBC OCI driver O7 or O8 ocixxx.dll Client Server Oracle JDBC Drivers: 3. Server-Side Driver Runs inside the database Java stored procedures must use this driver Stored procedure Oracle8i JDBC Server side driver C library SQL Engine Other JDBC Drivers JDBC-ODBC Bridge – Translates JDBC into open database connectivity (ODBC) calls – Allows communication with existing ODBC drivers when no JDBC driver is available Oracle Lite Driver For communication with an Oracle Lite database About JDBC URLs JDBC uses a URL to identify the database connection. jdbc:<subprotocol>:<subname> Protocol Subprotocol Database identifier jdbc:oracle:<driver>:@<database> JDBC URLs with Oracle Drivers Thin driver jdbc:oracle:thin:@<host>:<port>:<SID> OCI driver jdbc:oracle:oci8:@<TNSNAMES entry> Server-side driver: Use the default connection How to Make the Connection 1. Register the driver. DriverManager.registerDriver (new oracle.jdbc.driver.OracleDriver()); 2. Connect to the database. Connection conn = DriverManager.getConnection (URL, userid, password); Connection conn = DriverManager.getConnection ("jdbc:oracle:thin:@myhost:1521:orcl", "scott", "tiger"); Using Connection java.sql.Connection Creating Statement createStatment() prepareStatment(String) prepareCall(String) Transaction Management commit() rollback() Get database metadata getMetaData() close() isClosed() Conneciton related Demonstration Connection Stage 2: Query Connect Query Create a statement Process results Query the database Close The Statement Object A Statement object sends your SQL statement to the database. You need an active connection to create a JDBC statement. Statement has three methods to execute a SQL statement: – – – executeQuery() for QUERY statements executeUpdate() for INSERT, UPDATE, DELETE, or DDL statements execute() for either type of statement How to Query the Database 1. Create an empty statement object. Statement stmt = conn.createStatement(); 2. Execute the statement. ResultSet rset = stmt.executeQuery(statement); int count = stmt.executeUpdate(statement); boolean isquery = stmt.execute(statement); Querying the Database: Examples Execute a select statement. Statement stmt = conn.createStatement(); ResultSet rset = stmt.executeQuery ("select RENTAL_ID, STATUS from ACME_RENTALS"); • Execute a delete statement. Statement stmt = conn.createStatement(); int rowcount = stmt.executeUpdate ("delete from ACME_RENTAL_ITEMS where rental_id = 1011"); Stage 3: Process the Results Connect Query Step through the results Process results Close Assign results to Java variables The ResultSet Object JDBC returns the results of a query in a ResultSet object. A ResultSet maintains a cursor pointing to its current row of data. Use next() to step through the result set row by row. getString(), getInt(), and so on assign each value to a Java variable. How to Process the Results 1. Step through the result set. while (rset.next()) { … } 2. Use getXXX() to get each column value. String val = rset.getString(colname); String val = rset.getString(colIndex); while (rset.next()) { String title = rset.getString("TITLE"); String year = rset.getString("YEAR"); … // Process or display the data } How to Handle SQL Null Values Java primitive types cannot have null values. Do not use a primitive type when your query might return a SQL null. Use ResultSet.wasNull() to determine whether a column has a null value. while (rset.next()) { String year = rset.getString("YEAR"); if (rset.wasNull() { … // Handle null value } …} Mapping Database Types to Java Types ResultSet maps database types to Java types. ResultSet rset = stmt.executeQuery ("select RENTAL_ID, RENTAL_DATE, STATUS from ACME_RENTALS"); int id = rset.getInt(1); Date rentaldate = rset.getDate(2); String status = rset.getString(3); Col Name Type RENTAL_ID NUMBER RENTAL_DATE DATE STATUS VARCHAR2 Stage 4: Close Connect Query Close the result set Process results Close the statement Close Close the connection How to Close the Connection 1. Close the ResultSet object. rset.close(); 2. Close the Statement object. stmt.close(); 3. Close the connection (not necessary for server-side driver). conn.close(); Demonstration A Simple JDBC Program The DatabaseMetaData Object The Connection object can be used to get a DatabaseMetaData object. This object provides more than 100 methods to obtain information about the database. How to Obtain Database Metadata 1. Get the DatabaseMetaData object. DatabaseMetaData dbmd = conn.getMetaData(); 2. Use the object’s methods to get the metadata. DatabaseMetaData dbmd = conn.getMetaData(); String s1 = dbmd getURL(); String s2 = dbmd.getSQLKeywords(); boolean b1 = dbmd.supportsTransactions(); boolean b2 = dbmd.supportsSelectForUpdate(); The ResultSetMetaData Object The ResultSet object can be used to get a ResultSetMetaData object. ResultSetMetaData object provides metadata, including: – Number of columns in the result set – Column type – Column name How to Obtain Result Set Metadata 1. Get the ResultSetMetaData object. ResultSetMetaData rsmd = rset.getMetaData(); 2. Use the object’s methods to get the metadata. ResultSetMetaData rsmd = rset.getMetaData(); for (int i = 0; i < rsmd.getColumnCount(); i++) { String colname = rsmd.getColumnName(i); int coltype = rsmd.getColumnType(i); … } Demonstration Dynamic Query using MetaData The PreparedStatement Object A PreparedStatement object holds precompiled SQL statements. Use this object for statements you want to execute more than once. A prepared statement can contain variables that you supply each time you execute the statement. How to Create a Prepared Statement 1.Register the driver and create the database connection. 2.Create the prepared statement, identifying variables with a question mark (?). PreparedStatement pstmt = conn.prepareStatement("update ACME_RENTALS set STATUS = ? where RENTAL_ID = ?"); PreparedStatement pstmt = conn.prepareStatement("select STATUS from ACME_RENTALS where RENTAL_ID = ?"); How to Execute a Prepared Statement 1. Supply values for the variables. pstmt.setXXX(index, value); 2. Execute the statement. pstmt.executeQuery(); pstmt.executeUpdate(); PreparedStatement pstmt = conn.prepareStatement("update ACME_RENTALS set STATUS = ? where RENTAL_ID = ?"); pstmt.setString(1, "OUT"); pstmt.setInt(2, rentalid); pstmt.executeUpdate(); The CallableStatement Object A CallableStatement object holds parameters for calling stored procedures. A callable statement can contain variables that you supply each time you execute the call. When the stored procedure returns, computed values (if any) are retrieved through the CallabableStatement object. How to Create a Callable Statement Register the driver and create the database connection. Create the callable statement, identifying variables with a question mark (?). CallableStatement cstmt = conn.prepareCall("{call " + ADDITEM + "(?,?,?)}"); cstmt.registerOutParameter(2,Types.INTEGER); cStmt.registerOutParameter(3,Types.DOUBLE); How to Execute a Callable Statement 1. Set the input parameters. cstmt.setXXX(index, value); 2. Execute the statement. cstmt.execute(statement); 3. Get the output parameters. var = cstmt.getXXX(index); Using Transactions The server-side driver does not support autocommit mode. With other drivers: – – New connections are in autocommit mode. Use conn.setAutoCommit(false) to turn autocommit off. To control transactions when you are not in autocommit mode: – – conn.commit(): Commit a transaction conn.rollback(): Roll back a transaction Oracle JDBC Extensions Oracle provides many extensions to standard JDBC; for example: Connection OracleConnection Statement OracleStatement PreparedStatement OraclePreparedStatement CallableStatement OracleCallableStatement ResultSet OracleResultSet Advanced Programming Advanced Programming LOB Data type Advanced data type LOB Data type oracle.sql.BLOB – java.sql.Blob – Processing locator : getBLOB(), setBLOB() methods using jdk1.2.x oracle.sql.CLOB – java.sql.Clob – Processing locator : getCLOB(), setCLOB() methods using jdk1.2.x oracle.sql.BFILE – Oracle Specific Datatype BLOB Reading – getBinaryStream() 메서드 사용. – Return된 InputStream을 이용하여 처리(파일, 데이터베이스) Writing – getBinaryOutputStream() 메서드 사용 – java.io.OutputStream 객체를 이용하여 Writing BLOB : Reading 1. create statement 2. create resultset 3. get Blob locator 4. get InputStream 5. InputStream 처리 6. InputStream close Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery (“select blob_column from blob_table”); while (rs.next()) { BLOB blob = ((OracleResultSet)rs).getBLOB(1); InputStream is = blob.getBinaryStream(); int read = 0; while ( (read = is.read()) != -1) { // to do like writing a file using the stream } is.close(); } BLOB : Writing 1. create statement 2. create resultset 3. get Blob locator 4. get OutputStream 5. Source read 6. write blob 7. close stream Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery (“select blob_column from blob_table for update”); while (rs.next()) { BLOB blob = ((OracleResultSet)rs).getBLOB(1); OutputStream os = blob.getBinaryOutputStream(); InputStream src = new InputStream(…); byte [] buffer = new byte[1024]; int read = 0; while ( (read = src.read(buffer)) != -1) { os.write(buffer, 0, read); // write blob. } src.close(); os.close(); } CLOB Reading – – – getAsciiStream() : 아스키 스트림 getCharacterStream() : 유니코드 스트림. Return된 InputStream을 이용하여 처리(파일, 데이터베이스에 Writing) • Writing – – – getAsciiOutputStream() 메서드 사용해서 locator 획득 getCharacterOutputStream() 메서드 사용. java.io.OutputStream 객체를 이용하여 Writing CLOB : Reading 1. create statement 2. create resultset 3. get Clob locator 4. get InputStream 5. InputStream 처리 6. InputStream close Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery (“select clob_column from clob_table”); while (rs.next()) { CLOB blob = ((OracleResultSet)rs).getCLOB(1); Reader reader = clob.getCharacterStream(); char [] buffer = new char[10]; int length = 0; while ( (length = reader.read (buffer)) != -1) { System.out.println (new String(buffer)); } is.close(); } CLOB : Writing 1. create statement 2. create resultset 3. get clob locator 4. get OutputStream 5. Source read 6. write clob 7. close stream Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery (“select clob_column from clob_table for update”); while (rs.next()) { CLOB clob = ((OracleResultSet)rs).getCLOB(1); Writer writer = clob.getCharacterOutputStream(); FileInputStream src = new FileInputStream(“tmp”); byte [] buffer = new byte[512]; int read = 0; while ( (read = src.read(buffer)) != -1) { writer.write(buffer, 0, read); // write clob. } src.close(); writer.close(); } BFILE Locator : – getOracleObject(), getBFILE() 메서드 이용 oracle.sql.BFILE methods – fileExists(), isFileOpen() 메서드 – openFile(), closeFile() Creating a BFILE column Reading Writing BFILE : Creating a BFILE column cmd ="INSERT INTO my_bfile_table VALUES (’one’, bfilename(test_dir,’file1.data’))"; stmt.execute (cmd); cmd ="INSERT INTO my_bfile_table VALUES (’three’, null)"; stmt.execute(cmd); BFILE : Processing cmd = "SELECT * FROM my_bfile_table WHERE x = ’one’"; 1. select the locator rset = stmt.executeQuery (cmd); if (rset.next ()) { 2. Open the bfile BFILE bfile = ((OracleResultSet)rset).getBFILE (2); bfile.openFile(); InputStream in = bfile.getBinaryStream(); 3. get a binary stream int length ; byte[] buf = new byte[512]; while ((length = in.read(buf)) != -1) 4. InputStream 처리 { // to do something using byte buffer } 5. Close resoruce in.close(); bfile.closeFile(); Demonstration LOB Data Handling Advanced data type STRUCT Customized mapping ARRAY REF Struct The Oracle JDBC drivers materialize database objects as instances of Java objects Multiple ways to map between Java and SQL: – Default Mapping: JDBC materializes the object as an oracle.sql.STRUCT – Customized mappings: You explicitly specify mappings between database objects and Java classes SQLData CustomDatum JPublisher can help generate CustomDatum and SQLData mappings Default Mapping -oracle.sql.STRUCT Holds the pickle image (in the low level storage format) Contains a “values” array of oracle.sql.Datum objects Each attribute is already in its true data type getAttribute() retrieves values array as java.lang.Object[] Casts Struct to oracle.sql.STRUCT to use oracle.sql extensions – getOracleAttributes() returns value array as oracle.sql objects (native SQL format) getSQLTypeName() retrieves object type name References StructDescriptor for type information Access Data in oracle.sql.STRUCT ResultSet SSN oracle.sql.STRUCT Person(empid, name) (1001, ’Scott’) (1002, ‘Alice’) ... s rset.getObject(2) or rset.getSTRUCT(2) Object [ ] (0) 1001 (1) ‘Scott’ s.getAttributes() ResultSet rset = st.executeQuery("select * from hr_table"); while(rset.next()){ System.out.println(rset.getString(1)); // SSN STRUCT s = (STRUCT) rset.getObject(2); // Person Object[] attrs = s.getAttributes(); System.out.println(((BigDecimal) attrs[0]).intValue()); System.out.println((String) atts[0]); } Customized Mapping You can specify how our drivers materialize object data – – The JDBC 2.0 way -- SQLData The Oracle way -- CustomDatum The custom Java class you create must implement one of these interfaces Two steps: – – step 1) create the customized class step 2) register the customized mapping Implementing SQLData public class JCustomer implements java.sql.SQLData { private String sql_type; public int custNo; public String custName; public String getSQLTypeName() throws SQLException { return sql_type; } public void readSQL (SQLInput stream, String typeName) throws SQLException { sql_type = typeName; custNo = stream.readInt(); custName = stream.readString(); } public void writeSQL (SQLOutput stream) throws SQLException { stream.writeInt(custNo); stream.writeString(custName); } } Reading & Writing SQLData //put an entry in the typemap Map map = conn.getTypeMap(); // Dictionary in JDK 1.1.x map.put("CUSTOMER_INFO_T", Class.forName("JCustomer")); ResultSet rs = stmt.executeQuery("select VALUE p from CUSTOMER_TAB p"); while (rs.next()) { //retrieve the object JCustomer jc = (JCustomer) rs.getObject(1); PreparedStatement pstmt = conn.prepareStatement ("INSERT INTO NEW_CUSTOMER_TAB VALUES (?)"); pstmt.setObject(1, jc); // insert the object pstmt.executeUpdate(); } CustomDatum A flexible, efficient and powerful mapping You need to provide two classes: – one that implements the CustomDatumFactory interface – one that implements CustomDatum – The factory is used to generate the instance of type CustomDatum Can be used for any customized conversion Implementing CustomDatum & CustomDatumFactory public class JCustomer implements oracle.sql.CustomDatum { public Datum toDatum (OracleConnection c) throws SQLException { StructDescriptor sd = StructDescriptor.createDescriptor(“CUSTOMER_INFO_T",c); Object [] attributes = { empName, empNo }; return new STRUCT(sd, c, attributes); } } public class JCustomerFactory implement oracle.sql.CustomDatumFactory { public CustomDatum create(Datum d, int sqlType) throws SQLException { if (d == null) return null; Object [] attributes = ((STRUCT) d).getAttributes(); return new JCustomer(attributes[0], attributes[1]); } } Reading & Writing CustomDatum Statement s = conn.createStatement(); OracleResultSet rs = (OracleResultSet) s.executeQuery("SELECT VALUE p FROM CUSTOMER_TAB p"); while(rs.next()) { // retrieve the CustomDatum object Jcustomer jc = (JCustomer) rs.getCustomDatum (1, new JCustomDatumFactory()); PreparedStatement pstmt = conn.prepareStatement ("INSERT INTO NEW_CUSTOMER_TAB VALUES (?)"); // inserts a CustomDatum object pstmt.setObject(1, jc); pstmt.executeUpdate(); } Array Accesses collection types in database Handles both VARRAY and Nested Table oracle.sql.ARRAY holds the pickle image or locator bytes References ArrayDescriptor for type information getArray() retrieves the array contents in “default” JDBC types getOracleArray() retrieves elements in oracle.sql format getResultSet() retrieves elements as a ResultSet Access Data in Array oracle.sql.ARRAY ResultSet Name ‘Scott’ ‘Alice’ ... Phones varray(10) of varchar2(25) (‘111-2222’, ‘222-3333’) (‘333-4444’) ... s rset.getObject(2) or rset.getArray(2) or rset.getARRAY(2) s.getArray() Object [ ] (0) ‘111-2222’ (1) ‘‘222-3333’ ResultSet rset = st.executeQuery("select * from hr_table"); while(rset.next()){ System.out.println(rset.getString(1)); // Name ARRAY s = (ARRAY) rset.getObject(2); // Phones Object[] elems = s.getArray(); // retrieve elements for (int i<0; i<elems.length; i++) System.out.println((String) elems[i]); } Ref Accesses object reference in database oracle.sql.REF holds the ref getValue() to dereference setValue() to update the referenced object in the database immediately Access Data using REF ResultSet ADDR oracle.sql.REF (street_name, house_no) name varchar2, PEOPLE col1 REF ADDR (‘sam’, addr1) (‘sam’ 0000280209420D2400 ….) ref r.getValue() rset.getObject(2) or rset.getREF(2) or rset.getRef(2) ( ‘Samsung-dong’, 144-17 ) ResultSet rset = st.executeQuery("select name, ref(p) from people p"); while(rset.next()){ System.out.println(rset.getString(1)); // Name REF r = (REF)rset.getObject(2); // ADDR REF STURCT addr = r.getValue(); // get ADDR struct Object [] elems = addr.getAttributes(); // retrive attributes for (int i<0; i<elems.length; i++) System.out.println((String) elems[i]); } Demonstration Advanced Data type JDBC 2.0 Features JDBC 2.0 Features ResultSet enhancements Batch updates Statement Caching JNDI Connection Pooling & Caching Distributed Transactions ResultSet enhancements Scrollability – The ability to move backward as well as forward through a result set. – The ability to move to any particular position in the result set – Sensitivity must be specified. Sensitivity can detect whether data is changed or not. – Sensitive or Insensitive Mode Updatability – Can insert, modify, delete using while navigating a resultset 6 Types of ResultSet forward-only/read-only forward-only/updatable scroll-sensitive/read-only scroll-sensitive/updatable scroll-insensitive/read-only scroll-insensitive/updatable Scrollable Resultset Java Program Statement stmt = conn.createStatemen( ResultSet.TYPE_SCROLL_IN SENSITIVE, ResultSet.CONCURR_READ_ ONLY); ResultSet rset = stmt.executeQuery(); rset.absolute(2); ... Scrollable ResultSet Oracle 8i Cache Cursor next() previous() relative() absolute() first() last() Table APIs java.sql.Connection Statement createStatement (int resultSetType, int resultSetConcurrency) PreparedStatement prepareStatement (String sql, int resultSetType, int resultSetConcurrency) CallableStatement prepareCall (String sql, int resultSetType, int resultSetConcurrency) resultSetType resultSetConcurrency ResultSet.TYPE_FORWARD_ONLY ResultSet.CONCUR_READ_ONLY ResultSet.TYPE_SCROLL_INSENSITIVE ResultSet.CONCUR_UPDATABLE ResultSet.TYPE_SCROLL_SENSITIVE APIs java.sql.ResultSet void beforeFirst() throws SQLException void afterLast() throws SQLException boolean first() throws SQLException boolean last() throws SQLException boolean absolute(int row) throws SQLException boolean relative(int row) throws SQLException void deleteRow(int row) throws SQLException void updateXXX(int idx, XXX x) throws SQLException void updateRow() throws SQLException void moveToInsertRow () throws SQLException void moveToCurrentRow() throws SQLException void insertRow() throws SQLException Example : Backward Statement stmt = conn.createStatement (ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = stmt.executeQuery("SELECT empno, sal FROM emp"); rs.afterLast(); while ( rs.previous() ) { System.out.println(rs.getString("empno") + " " + rs.getFloat("sal")); } ... Example : delete row ... rs.absolute(5); rs.deleteRow(); ... Example : update row Statement stmt = conn.createStatement (ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = stmt.executeQuery("SELECT empno, sal FROM emp"); if (rs.absolute(10)) // (returns false if row does not exist) { rs.updateString(1, "28959"); rs.updateFloat("sal", 100000.0f); rs.updateRow(); } // Changes will be made permanent with the next COMMIT operation. ... Example : insert row ... Statement stmt = conn.createStatement (ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = stmt.executeQuery("SELECT empno, sal FROM emp"); rs.moveToInsertRow(); rs.updateString(1, "28959"); rs.updateFloat("sal", 100000.0f); rs.insertRow(); // Changes will be made permanent with the next COMMIT operation. rs.moveToCurrentRow(); // Go back to where we came from... ... Visibility of Internal & External Changes Can See Can See Can See Internal Internal Internal DELETE? UPDATE? INSERT? Can See Can See Can See External External External DELETE? UPDATE? INSERT? forward-only no yes no no no no scroll-sensitive yes yes no no yes no scroll-insensitive yes yes no no no no Detection of External Changes – no use of rowDeleted(), rowUpdated(), rowInserted() Oracle Implementation of Scroll-Sensitive Result Sets – the concept of a window based on the fetch size refreshRow() Demonstration ResultSet Batch updates Grouping multiple UPDATE, DELETE, or INSERT statements into a single "batch“ Performance improvement because of reducing round trip !! Two type of batch update – Standard model : Sun’s JDBC Spec. since 8.1.6 – Oracle specific model : Oracle’s implementation. since 8.1.5 Don’t mix these types in a single connection Batch update : Oracle specific model Oracle model use batch value and results in implicit processing. The driver knows ahead of time how many operations will be batched. Only OraclePreparedStatement is suppored. Casting is required. batch value : 5 ~ 30 (default 1) sendBatch() method will be executed, when – – – commit() method call statement’close() method call connection’ close() method call Examples : Oracle Specific PreparedStatement ps = conn.prepareStatement("insert into dept values (?, ?, ?)"); //Change batch size for this statement to 3 ((OraclePreparedStatement)ps).setExecuteBatch (3); ps.setInt(1, 23); ps.setString(2, "Sales"); ps.setString(3, "USA"); ps.executeUpdate(); //JDBC queues this for later execution … //Third insert statement ps.setInt(1, 26); ps.setString(2, "HR"); ps.setString(3, "Mongolia"); ps.executeUpdate(); //JDBC send the requests to the database ((OraclePreparedStatement)ps).sendBatch(); // JDBC sends the queued request conn.commit(); ps.close(); Batch update : Standard model Explicitly add statement to the batch using addBatch() method explicitly executing the batch using an executeBatch() method after finish to add batch. Statement, PreparedStatement, CallableStatement are supported. Example : Standard conn.setAutoCommit(false); PreparedStatement pstmt = conn.prepareStatement("INSERT INTO employees VALUES(?, ?)"); pstmt.setInt(1, 2000); pstmt.setString(2, "Milo Mumford"); pstmt.addBatch(); pstmt.setInt(1, 3000); pstmt.setString(2, "Sulu Simpson"); pstmt.addBatch(); int[] updateCounts = pstmt.executeBatch(); conn.commit(); pstmt.close(); ... Performance Issues – – – – Disable Auto-Commit Mode 매번 커밋하지 않고 필요할 때에만, 커밋하도록 한다.기본적으로 'auto-commit'으로 되어 있다. Prefetch Rows 질의 시, 클라이언트가 미리 패치하는 행의 수 명시. 기본적으로는 10개의 행을 패치한다. Batch Updates 오라클 JDBC 드라이버에서는 삽입/갱신 작업을 배치 작업으로 처리할 수 있다. Define Column types 데이터베이스에게 타입을 알려주는 팁 설정. 데이터 베이스 컬럼 알기 위한 network round-trip을 줄일 수 있다. Performance Issues Disable Auto-Commit Mode conn.setAutoCommit (false); Prefetch Rows conn.setDefaultRowPrefetch (20); Batch Updates conn.setDefaultExecuteBatch (10); stmt.setExecuteBatch (15); Define Column types stmt.defineColumntype (1, <type> ); stmt.defineColumnType (1, <type>, <length> ); Statement Caching Performance Improved by Caching Executable Statements – Repeated use (e.g. loop) prevent the overhead of repeated cursor creation prevent repeated statement parsing and creation – – Cache statements associated with a particular physical connection Two Types implicit explicit Using Statement Caching Enabling and Disabling Statement Caching ((OracleConnection)conn).setStmtCacheSize(10) ((OracleConnection)conn).setStmtCacheSize(0); Checking for Statement Creation Status int state = ((OracleStatement)stmt).creationState() Physically Closing a Cached Statement – The close() method of a statement object caches the statement instead of closing it. Using Implicit Statement Caching Using Explicit Statement Caching ((OraclePreparedStatement(pstmt).closeWithKey(“mykey”); pstmt=((OracleConnection)conn).prepareStatementWithKey(“mykey”); JNDI JNDI(Java Naming and Directory Interface) can be used in addition to the JDBC driver manager to manage data sources and connections. Don’t care about JDBC connection string. It isn’t hard coded anymore. Can access databases using their names not connection string. Steps – – – – creating datasource : set datasource’s properties Register : register connection properties to JNDI Server Lookup : find datasource object using given name within JNDI Server. Create Connection : using datasource Example : JNDI // Creating OracleDataSource ods = new OracleDataSource(); ods.setDriverType("oci8"); ods.setServerName("dlsun999"); ods.setNetworkProtocol("tcp"); ods.setDatabaseName("816"); ods.setPortNumber(1521); ods.setUser("scott"); ods.setPassword("tiger"); // Register Context ctx = new InitialContext(); ctx.bind("jdbc/sampledb", ods); Example : JNDI // lookup and create connection OracleDataSource odsconn = (OracleDataSource)ctx.lookup("jdbc/sampledb"); Connection conn = odsconn.getConnection(); ... Connection Pooling Connection pooling is a framework for caching database connection reuse of physical connections. reduce overhead of creating new connections. Connection pool data source – Factory to creating pooled connections Pooled connection – represents a physical connection to a data source. – Factory for the Connection Objects. Connection Cache Connection Pooling Connection getConnection getPooledConnection PooledConnection ConnectionPoolDataSource ( close or error event) ConnectionEvent ConnectionEventListener Connection Pooling : API public interface ConnectionPoolDataSource { PooledConnection getPooledConnection() throws SQLException; PooledConnection getPooledConnection(String user, String password) throws SQLException; } public interface PooledConnection { Connection getConnection() throws SQLException; void close() throws SQLException; void addConnectionEventListener(ConnectionEventListener listener) ... ; void removeConnectionEventListener(ConnectionEventListener listener); void setStmtCacheSize(int size); void setStmtCacheSize(int size, boolean clearMetaData); int getStmtCacheSize(); } Example : Connection Pooling // Create a OracleConnectionPoolDataSource instance OracleConnectionPoolDataSource ocpds = 1. Creating ConnectionPoolDataSource new OracleConnectionPoolDataSource(); // Set connection parameters 2. Creating PooledConnection ocpds.setURL("jdbc:oracle:oci8:@"); ocpds.setUser("scott"); 3. Creating Connection Object ocpds.setPassword("tiger"); // Create a pooled connection PooledConnection pc = ocpds.getPooledConnection(); // Get a Logical connection Connection conn = pc.getConnection(); Connection Cache JDBC 2.0 doesn’t mandate that JDBC vendors provide one, but they highly recommend it 2-fold strategy – We implemented a cache with 3 commonly used schemes – Provide an interface for the end user to develop their own cache but they still would like to reuse OracleConnectionEventListener OracleConnectionCache An interface one needs to implement if they like to have their own Cache but reuse our infrastructure Extends DataSource interface Additional methods – reusePooledConnection(PooledConnection) – closePooledConnection(PooledConnection) – close OracleConnectionCacheImpl Oracle’s implementation of a basic Cache Extends OracleDataSource and implements OracleConnectionCache JNDI Referenceable Implements java.io.Serializable Simple, Easy and Efficient 3 Schemes are provided OracleConnectionCacheImpl Dynamic : A typical grow and shrink scheme. Could create new connections beyond the maximum limit when all the existing ones are active. This is the default Scheme. Fixed with No Wait : Request for new connections beyond the maximum limit will return null. Fixed With Wait : Request for new connections are blocked when all the connections in the cache up to the limit are active and consumed. OracleConnectionCacheImpl All Connections in a cache are to the same Database and have the schema Connections obtained are logical connections Connection Properties can be set in 2 ways – Set Properties directly like on DataSource – Through a ConnectionPoolDataSource Demonstration Connection Pooling Distributed Transactions A set of two or more related transactions that must be managed in a coordinated way. Global transaction vs Branch transaction X/Open Standard : XA. not specific java Each transaction is managed by Transaction Manager that implements Java Transaction API (JTA). XA functionality is usually isolated from a client application, being implemented instead in a middletier environment such as an application server. Distributed Transactions : XA Components XA data source – extensions of connection pool data sources and other data sources, and similar in concept and functionality. XA connection – extensions of pooled connection XA resource – – – Database resource XA connection : XA resource = 1:1 Physical DB session : XA resource = 1:1 Transaction ID – Identifier of each transaction branch. Distributed Transactions : XA APIs oracle.jdbc.xa package – – OracleXid OracleXAException oracle.jdbc.xa.client package – – XADatasource, XAConnection, XAResource outside Oracle database oracle.jdbc.xa.server package – – XADatasource, XAConnection, XAResource inside Oracle database Distributed Transactions : XA APIs public interface XADatasource . XAConnection getXAConnection() throws SQLException public interface XAConnection extends PooledConnection . XAResource getXAResource() throws SQLException; public interface XAResource . void commit(Xid xid, boolean onePhase) throws XAException; . void end(Xid xid, int flags) throws XAException; . void forget(Xid xid) throws XAException; . int prepare(Xid xid) throws XAException; . Xid[] recover(int flag) throws XAException; . void rollback(Xid xid) throws XAException; . void start(Xid xid, int flags) throws XAException; . boolean isSameRM(XAResource xares) throws XAException; Example : Distributed Transaction XA with Two-Phase Commit Operation 1. Start transaction branch #1. 2. Start transaction branch #2. 3. Execute DML operations on branch #1. 4. Execute DML operations on branch #2. 5. End transaction branch #1. 6. End transaction branch #2. 7. Prepare branch #1. 8. Prepare branch #2. 9. Commit branch #1. 10. Commit branch #2. SQLJ SQLJ Standard way to embed SQL statements in Java programs. More concise than JDBC Early checking of SQL statements eliminates many run time errors: – SQL syntax errors – Incorrect assumption of table structures – Java/SQL type mismatch Comparing SQLJ with JDBC JDBC java.sql.PreparedStatement stmt; stmt = conn.prepareStatement (“INSERT INTO emp ” + “VALUES(?, ?, ?, ?, ?”); stmt.setString(1, name); stmt.setInt(2, dept); stmt.setString(3, mgr); stmt.setDouble(4, sal); stmt.setDate(5,today); stmt.execute(); stmt.close(); SQLJ #sql { INSERT INTO emp VALUES (:name,:dept,:mgr, :sal,:today)}; What you need to learn SQLJ program template Issuing a query Updating a table using a statement with bind variables SQLJ Program Template import java.sql.*; // Program uses JDBC import oracle.sqlj.runtime.*; // and SQLJ class Example1 { public static void main (String args []) throws SQLException { // Your SQLJ code goes here } } SQLJ clauses • A executable SQLJ clause has this form: #sql { SQL-statement } ; • The SQL statement appears inside the curly braces: #sql { DELETE FROM tab WHERE col < 0 }; Doing a Query Define an Iterator Type Create instances of the Iterator Type Populate Iterator with results from query Use Iterator methods to access the data Define an Iterator Type • The Iterator definition lists the SQL names and the Java types of the result columns #sql iterator EmpCursor (String ENAME, Double SAL); A class EmpCursor will be produced with the following methods: boolean next(); //Moves to next row, if any String ENAME(); //Gets column ENAME as String Double SAL(); //Gets column SAL as Double Use the Iterator Type to do a Query • Declare variable of the Iterator Type • Populate iterator with results from query • Use the Iterator methods to access data EmpCursor c; #sql c = {select ENAME, SAL from EMP}; while (c.next ()) { String ename = c.ENAME (); Double sal = c.SAL (); } How to do an Update • The SQL statement may have Java bind variables prefixed with a colon ':' String ename = “Seik Waljay”; Double sal = 15000; #sql { update EMP set SAL = :sal where ENAME = :ename }; Q&A