710 likes | 863 Views
Fejlett Programoz ási Technikák 2. 15 / 7. Az előző előadás tartalma:. JFC és Swing Múlt Felépítés Java Bean Felső szintű konténerek Középső szintű konténerek Elemek Eseménykezelés Rajzolás. A mai előadás tartalma:. Java Applet Felépítése Tulajdonságai Paraméterátadás JDBC
E N D
Az előző előadás tartalma: • JFC és Swing • Múlt • Felépítés • Java Bean • Felső szintű konténerek • Középső szintű konténerek • Elemek • Eseménykezelés • Rajzolás
A mai előadás tartalma: • Java Applet • Felépítése • Tulajdonságai • Paraméterátadás • JDBC • Típusai • Kapcsolat típusok • Statement objektumok • RecordSet • Tranzakciók
Források: • http://java.sun.com/products/jdbc/ • http://jdl.sun.com/webapps/download/Display?BundleId=7219&button=Continue • http://java.sun.com/j2se/1.4.2/docs/api/java/sql/package-summary.html • http://www.mindview.net/Books/TIJ/ • http://www.cab.u-szeged.hu/WWW/java/kiss/jdbc.html
Java Applet • Kliens oldalon fut • Beágyazható a HTML-be • Az APPLET elemmel lehet beágyazni • Akkor célszerű használni, ha nincs egyszerűbb megoldás (titkosítás, táblázat, nyomtatás) • Korlátozottabb mint a Java alkalmazás
Nem garantált, hogy a másik oldalon van Java <OBJECT classid = "clsid:CAFEEFAC-0014-0001-0000-ABCDEFFEDCBA" codebase = "http://java.sun.com/products/plugin/autodl/jinstall-1_4_1-windows-i586.cab#Version=1,4,1,0" WIDTH = 100 HEIGHT = 50 > <PARAM NAME = CODE VALUE = Applet1 > <PARAM NAME = "type" VALUE = "application/x-java-applet;jpi-version=1.4.1"> <PARAM NAME = "scriptable" VALUE = "false"> <COMMENT> <EMBED type = "application/x-java-applet;jpi-version=1.4.1" CODE = Applet1 WIDTH = 100 HEIGHT = 50 scriptable = false pluginspage = "http://java.sun.com/products/plugin/index.html#download"> <NOEMBED> </NOEMBED> </EMBED> </COMMENT> </OBJECT> <!-- <APPLET CODE = Applet1 WIDTH = 100 HEIGHT = 50> </APPLET> --> • HTMLconverter
Alapok • Az Applet osztályból származtatandó amennyiben AWT elemeket szeretnénk használni • A JApplet osztályból származtatandó amennyiben Swing elemeket is szeretnénk használni
<HTML> <HEAD> <TITLE> Teszt </TITLE> </HEAD> <BODY> <APPLET CODE="HelloWorld.class" WIDTH="150" HEIGHT="25"> </APPLET> </BODY> </HTML> Példa import javax.swing.*; import java.awt.*; public class HelloWorld extends JApplet { JLabel label; String szoveg; public void start() { szoveg = szoveg + " - " + "Start"; label.setText(szoveg); } public void stop() { szoveg = szoveg + " - " + "Stop"; label.setText(szoveg); } public void destroy() { szoveg = szoveg + " - " + "Destroy"; label.setText(szoveg); } public void init() { szoveg = new String("Init"); label = new JLabel(szoveg); label.setHorizontalAlignment(JLabel.CENTER); label.setBorder(BorderFactory.createMatteBorder(1,1,2,2,Color.black)); getContentPane().add(label, BorderLayout.CENTER); } }
Rajz példa import javax.swing.JApplet; import java.awt.Graphics; public class Rajz extends JApplet { public void paint(Graphics g) { g.drawLine(15,10,210,10); g.drawLine(15,30,210,30); g.drawString(”Szöveg”,25,25); } }
Metódusok • init - inicializálja az appletet minden újraindítás, újratöltés után • start – az applet inicializálása után fut le, amikor egy oldalról elmegyünk és visszatérünk akkor csak ez és a stop metódus fut le • stop – az applet leállítása esetén fut le • destroy - az applet újraindítása valamint kilépés esetén fut le • paint – AWT használata esetén érdekes, segítségével viszonylag egyszerűen rajzolhatunk
Az appletek korlátai • a biztonságos működés érdekében a következő korlátok léteznek: • nem definiálhatunk natív metódusokat • a futtató gépen nem írhat, olvashat fájlokat • nem hozhat létre hálózati kapcsolatokat (a szervert kivéve) • nem futtathat programokat a kliensen • nem olvashatja a rendszer tulajdonságok egy részét • a megjelenő ablakokban figyelmeztet arra, hogy azok Java Applet ablakok • digitálisan aláírt appletekre a fentiek nem feltétlenül vonatkoznak (policy fájl) (http://developer.java.sun.com/developer/technicalArticles/Security/Signed/)
Amit Applettel meg lehet valósítani • szinte minden Swing és AWT elem használható • a szerverrel hálózati kapcsolatot tud kiépíteni • az azonos oldalon lévő appletek publikus metódusait meghívhatjuk (böngésző függő) • a helyi erőforrásról betöltött appletek nem rendelkeznek a hálózatról letöltött appletek korlátaival
Appletek létrehozása • Forras.java • javac Forras.java • a legtöbb böngésző az oldal frissítésével nem frissíti az appleteket (shift, ctrl + refresh) • végső megoldás: kiüríteni a böngésző gyorstárát, kilépni a böngészőből, belépni a böngészőbe • érdemes appletviewer-t használni a tesztelésre • appletviewer forras.html • figyeljünk arra, hogy a helyi elérési útvonal ne tartalmazzon szóközöket
Applet desktop alkalmazás import javax.swing.*; import java.awt.*; public class Applet1c extends JApplet { public void init() { getContentPane().add(new JLabel("Applet!")); } public static void main(String[] args) { JApplet applet = new Applet1c(); JFrame frame = new JFrame("Applet1c"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(applet); frame.setSize(100,50); applet.init(); applet.start(); frame.setVisible(true); } }
Appletek használata • A showStatus(); metódussal írhatunk a státusz sorba • másik applet metódushívás public class Sender extends Applet implements ActionListener { . . receiver = getAppletContext().getApplet(receiverName); ((Receiver)receiver).processRequestFrom(myName); } . . . public class Receiver extends Applet { public void processRequestFrom(String senderName) { label.setText("Received message from " + senderName + "!"); repaint(); } • Enumeration e = getAppletContext().getApplets(); • Applet applet = (Applet)e.nextElement();
Paraméterek • <PARAM NAME=”nev” VALUE=”vili”> • String nev = getParameter("nev") • <APPLET CODEBASE=”URL”>
Szálak • sok böngésző az appleteket külön szálakban futtatja • gyakran külön szál csoportban • Párhuzamos feladatok végrehajtására szálakat használhatunk • Runnable interfészt kell megvalósítani
Kommunikáció a szerverrel • HTML (PARAM) • java.net (servlet listerner) • RMI • CORBA • JDBC
SQL, ODBC • SQL (Sturctured Query Language) • adatbázis, tábla, sor , oszlop • relációs adatbázis • lekérdezés • módosító lekérdezés • nézet • ODBC (Open Database Connectivity) • X/Open SQL CLI • C nyelven alapuló interfész • egységes felületet biztosít az adatbázisokhoz • a gyártók saját meghajtókat írnak • PC szabvány (csaknem ipari szabvány)
JDBC • A Java platform legfontosabb összetevője • Platform és szállító független • Egy egyszerű Java API a programozók számára • JDBC meghajtó menedzser • Gyártó specifikus meghajtók mellyel az egyes gyártók optimalizálhatják a kapcsolatot • Hasonló megoldás mint a Microsoft igen sikeres ODBC megoldása (C nyelv) • Az adatok titkosítása az szállító meghajtó feladata
JDBC • JDBC 1.0 • SQL 92 • egyszerű hívásszintű interfész • JDBC 2.0 • sokkal összetettebb funkciók, alkalmazásszerverek • connection pooling • distributed transaction • JDBC 3.0 • SQL 99
JDBC meghajtók • JDBC-ODBC bridge plus ODBC driver • JDBC-t ODBC-re alakítja • az ODBC meghajtó kommunikál az adatbázissal • JDBC/ODBC bridge • nem támogatja a JDBC2-t • az ODBC-t kell beállítanunk • nem ajánlott a haszálata • Native-API partly-Java driver • a meghajtó részben Java nyelven részben más nyelven íródott • platform specifikus • JDBC-Net pure Java driver • egyszerű Java kliens könyvtár mely adatbázis független hálózati protokollon keresztül kommunikál egy szerver komponenssel mely ezt továbbítja az adatbázisnak • Native-protocol pure Java driver • egyszerű Java könyvtár mely közvetlenül az adatbázissal kommunikál
Miért nem ODBC • Bonyolult • Kevés utasítás, bonyolult szintaxis • C specifikus, Pointer függő • Kevésbé biztonságos, nehezebben telepíthető mint a JDBC
Használata • Használható • Java alkalmazásokban • Applet-ekben • csak a szerverrel tud kapcsolatot létesíteni • Három, vagy több rétegű alkalmazásokban http, RMI, … Adatbázis Szever Kliens Középső réteg (Servlet, EJBean) JDBC
JDBC installálása • PostgreSQL • pgjdbc2.jar ->…\lib\ext • postmaster –i • pg_hba.conf • CLASSPATH • windows: • http://www.ejip.net/faq/postgresql_win_setup_faq.jsp
JDBC kapcsolat felépítés I. • Meghajtó betöltése: • try { Class.forName("org.postgresql.Driver"); } catch(java.lang.ClassNotFoundException e) { System.err.print("ClassNotFoundException: "); System.err.println(e.getMessage()); } • java -Djdbc.drivers=org.postgresql.Driver Teszt • Adatbázis címzése: • jdbc:<alprotokoll>:<adatbázis hivatkozás> • jdbc:odbc://teszt.com:5000;UID=scott;PWD=tiger • jdbc:postgresql://160.114.36.248/teszt
JDBC kapcsolat felépítés II. • Kapcsolat objektum: • Connection con; • con = DriverManager.getConnection(url, "Rendszergazda", ”x"); • Kifejezés: • Statement stmt; • stmt = con.createStatement(); • stmt.close(); • con.close(); • kilépéskor le kell zárnunk minden kapcsolatot !! (a szemétgyűjtő nem tudja megtenni helyettünk a statemenet-et igen)
Példa: import java.sql.*; public class Teszt { public static void main(String args[]) { String url = "jdbc:postgresql://160.114.36.248/teszt"; Connection con; String createString; createString = "create table Teszt1 (COF_NAME VARCHAR(32), " + "SUP_ID INTEGER, PRICE FLOAT, SALES INTEGER, " + "TOTAL INTEGER)"; Statement stmt; try {Class.forName("org.postgresql.Driver");} catch(java.lang.ClassNotFoundException e) { System.err.print("ClassNotFoundException: "); System.err.println(e.getMessage());} try { con = DriverManager.getConnection(url, "Rendszergazda", "Alert"); stmt = con.createStatement(); stmt.executeUpdate(createString); stmt.close(); con.close(); } catch(SQLException ex) { System.err.println("SQLException: " + ex.getMessage());} } }
JDBC kapcsolat felépítés III. • Connection Pooling • ConnectionPoolDataSource interfész • 1:X kapcsolat • fizikai kapcsolatok helyett logikai kapcsolatok • a kliens nem érzékel semmit • Alkalmazás szerver biztosítja ezt a funkciót (Tomcat is)
Példa com.acme.jdbc.ConnectionPoolDS cpds = new com.acme.jdbc.ConnectionPoolDS(); cpds.setServerName(“bookserver”); cpds.setDatabaseName(“booklist”); cpds.setPortNumber(9040); cpds.setDescription(“Connection pooling for bookserver”); Context ctx = new InitialContext(); ctx.bind(“jdbc/pool/bookserver_pool”, cpds); com.acme.appserver.PooledDataSource ds = new com.acme.appserver.PooledDataSource(); ds.setDescription(“Datasource with connection pooling”); ds.setDataSourceName(“jdbc/pool/bookserver_pool”); Context ctx = new InitialContext(); ctx.bind(“jdbc/bookserver”, ds); Context ctx = new InitialContext(); DataSource ds = (DataSource)ctx.lookup(" jdbc/bookserver"); Connection con = ds.getConnection("user", "pwd");
Connection • Egy kapcsolatot jelent az adatbázissal • Egy alkalmazásnak egy-vagy több kapcsolat objektuma lehet, egy-vagy több adatbázissal • Connection.getMetaData • DatabaseMetaData, információ az adatbázisról • DriverManager.getConnection(URL) • a DriverManager megpróbál egy megfelelő meghajtót keresni az URL-ben szereplő adatbázishoz • DataSource ds.getConnection("user", "pwd");
Metadata • DatabaseMetaData dbmd = con.getMetaData(); • kb. 150 metódust használhatunk • a legtöbb resultset objektumot ad vissza • sok metódus bonyolult névvel rendelkezik, célszerű olyan metódusokat használni melyek ezeket megadják
Metadata – Általános információk • getURL • getUserName • getDatabaseProductVersion, getDriverMajorVersion and • getDriverMinorVersion • getSchemaTerm, getCatalogTerm and getProcedureTerm • nullsAreSortedHigh and nullsAreSortedLow • usesLocalFiles and usesLocalFilePerTable • getSQLKeywords
Metadata-Lehetőségek • supportsAlterTableWithDropColumn • supportsBatchUpdates • supportsTableCorrelationNames • supportsPositionedDelete • supportsFullOuterJoins • supportsStoredProcedures • supportsMixedCaseQuotedIdentifiers • supportsANSI92EntryLevelSQL • supportsCoreSQLGrammar
Metadata - korlátok • getMaxRowSize • getMaxStatementLength • getMaxTablesInSelect • getMaxConnections • getMaxCharLiteralLength • getMaxColumnsInTable
Statement • paraméter nélküli kifejezések • egyszerű SQL kifejezések létrehozására használandó • executeQuery ( • egyszerű lekérdezés Select * from t • executeUpdate • INSERT • UPDATE • DELETE • CREATE TABLE • DROP TABLE • a visszatérési értéke egy integer mely az érintett sorok számát adja meg egyébként 0 • execute • olyan esetekben használják amikor több mint egy válasz érkezik Connection con = DriverManager.getConnection(url, "sunny", ""); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table2");
Példa: Execute Statement stmt = conn.createStatement(); boolean b = stmt.execute(sql); if (b == true) { // b is true if a ResultSet is returned ResultSet rs; rs = stmt.getResultSet(); while (rs.next()) { ... } } else { // b is false if an update count is returned int rows = stmt.getUpdateCount(); if (rows > 0) { ... } }
Automatikusan Generált Kulcsok • Statement.RETURN_GENERATEDKEYS • getGeneratedKeys(); Statement stmt = conn.createStatement(); int rows = stmt.executeUpdate("INSERT INTO ORDERS " + "(ISBN, CUSTOMERID) " + "VALUES (195123018, ’BILLG’)", Statement.RETURN_GENERATED_KEYS); ResultSet rs = stmt.getGeneratedKeys(); boolean b = rs.next(); if (b == true) { // retrieve the new key value ... }
Prepared Statement • a Statement alosztálya • előre fordított SQL kifejezések • egy-vagy több paramétere lehet (IN) • több metódust használhatunk az IN paraméterek beállítására • sokkal hatékonyabb lehet mint a Statement objektum (előre fordított) • gyakran használt kifejezések létrehozására használandó • többször futtatható, a beállított paraméterek megmaradnak
Példa Connection con = DriverManager.getConnection( "jdbc:my_subprotocol:my_subname"); con.setTransactionIsolation(TRANSACTION_READ_COMMITTED); PreparedStatement pstmt = con.prepareStatement( "SELECT EMP_NO, SALARY FROM EMPLOYEES WHERE EMP_NO = ?", ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); pstmt.setFetchSize(25); pstmt.setString(1, "1000010"); ResultSet rs3 = pstmt.executeQuery(); pstmt.setString(1, "Hi"); for (int i = 0; i < 10; i++) { pstmt.setInt(2, i); int rowCount = pstmt.executeUpdate(); } • setNull
Callable Statement • segítségével SQL tárolt eljárásokat futathatunk • supportsStoredProcedures() • getProcedures() • {? = call procedure_name[(?, ?, ...)]} • IN paraméterek • OUT paraméterek • regisztrálni kell • nincs külön lehetőség nagy adatok kezelésére • INOUT paraméterek
Példa IN CallableStatement cstmt = con.prepareCall( "{call updatePrices(?, ?)}"); cstmt.setString(1, "Colombian"); cstmt.setFloat(2, 8.49f); cstmt.addBatch(); cstmt.setString(1, "Colombian_Decaf"); cstmt.setFloat(2, 9.49f); cstmt.addBatch(); int [] updateCounts = cstmt.executeBatch();
Példa OUT CallableStatement cstmt = con.prepareCall( "{call getTestData(?, ?)}"); cstmt.registerOutParameter(1, java.sql.Types.TINYINT); cstmt.registerOutParameter(2, java.sql.Types.DECIMAL); ResultSet rs = cstmt.executeQuery(); // . . . byte x = cstmt.getByte(1); java.math.BigDecimal n = cstmt.getBigDecimal(2);
Példa INOUT CallableStatement cstmt = con.prepareCall("{call reviseTotal(?)}"); cstmt.setByte(1, (byte)25); cstmt.registerOutParameter(1, java.sql.Types.TINYINT); cstmt.executeUpdate(); byte x = cstmt.getByte(1);
Result Set • Az előző három objektum eredménye • Alapesetben nem írható és nem görgethető (csak egyszer lehet rajta végigmenni) • A JDBC 2.0 API ezeket lehetővé teszi • Nem minden meghajtó képes erre (pl.: postgresql) • getXXX(név vagy sorszám) metódusok (select a, select * ) • getMetaData • updateRow(), insertRow(), deleteRow(), refreshRow() • JDBC 2.0 • previous • first • last • absolute • relative • afterLast • beforeFirst
Meta Data: ResultSet rs = stmt.executeQuery(sqlString); ResultSetMetaData rsmd = rs.getMetaData(); int colType [] = new int[rsmd.getColumnCount()]; for (int idx = 0, int col = 1; idx < colType.length; idx++, col++) colType[idx] = rsmd.getColumnType(col);
Result set (JDBC 3.0) • Kurzor: • TYPE_FORWARD_ONLY • TYPE_SCROLL_INSENSITIVE • TYPE_SCROLL_SENSITIVE • Párhuzamosság • CONCUR_READ_ONLY • CONCUR_UPDATABLE • Tarthatóság: • HOLD_CURSORS_OVER_COMMIT • CLOSE_CURSORS_OVER_COMMIT • Használata: Connection conn = ds.getConnection(user, passwd); Statement stmt = conn.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT); ResultSet rs = stmt.executeQuery(“select author, title, isbn from booklist”);