Tvorba informačních systémů Michal Krátký, Miroslav Beneš Katedra informatiky VŠB Technická univerzita Ostrava Tvorba informačních systémů, 2007/2008 c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 1/51
Obsah 5. Datová vrstva informačních systémů Datová vrstva,,, ADO.NET. Bezpečnost, SQL Injection, Transakce, Využití objektově-relačního modelu. c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 2/51
Datová vrstva 5. Datová vrstva informačních systémů Oddělení aplikace od přístupu do databáze. Standardizovaný dotazovací jazyk SQL. API v programovacím jazyce ODBC, JDBC, ADO.NET. c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 3/51
Standard pro přístup do databáze, SQL Access group, 1992. Umožňuje dotazovat data z libovolné aplikace bez ohledu v jaké databázi jsou uložena. Vložena mezivrstva - ovladač, překládající uživatelské dotazy na dotazy databáze. Správce ovladačů Driver Manager. SŘBD podporující přístup přes ODBC: ODBC-compliant. Od verze 2.0 je podporováno SQL. Standardy: X/Open a ISO: SQL Call Level Interface (SQL/CLI). c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 4/51
Architektura ODBC c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 5/51
Typy ovladačů 5. Datová vrstva informačních systémů Ovladače založené na souborech přímý přístup k datům (ovladače = zdroj dat), analýza a interpretace dotazů, dbase. Ovladače založené na SŘBD dotazy se předávají ke zpracování SŘBD, transformace ODBC SQL na konkrétní dialekt SQL. c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 6/51
JDBC, provedení dotazu 1 Připojení k datovému zdroji. 2 Inicializace. 3 Vytvoření a provedení dotazu. 4 Získání výsledku. 5 Ukončení transakce. 6 Odpojení od datového zdroje. c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 7/51
Připojení k datovému zdroji / / Alokace zastupce pro spravce ovladacu ODBC SQLHENV henv ; SQLAllocHandle (SQL_HANDLE_ENV, SQL_NULL_HANDLE, & henv ) ; / / Deklarace pozadovane verze ODBC SQLSetEnvAttr ( henv, SQL_ATTR_ODBC_VERSION, ( SQLPOINTER ) SQL_OV_ODBC3, 0 ) ; / / Alokace zastupce pro databazove p r i p o j e n i SQLHDBC hdbc1 ; SQLAllocHandle (SQL_HANDLE_DBC, henv, & hdbc ) ; / / P r i p o j e n i k databazi, zdroj, u z i v a t e l, heslo SQLConnect ( hdbc, database, SQL_NTS, user, SQL_NTS, password, SQL_NTS ) ; c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 8/51
Inicializace aplikace / / Z i s k a n i i n f o r m a c i o SRBD, ovladaci,... SQLCHAR dbms_name [ 4 0 ] ; SQLGetInfo ( hdbc, SQL_DBMS_NAME, dbms_name, sizeof (dbms_name ), NULL ) ; / / Alokace zastupce pro p r i k a z ( dotaz ) SQLHANDLE hstmt ; SQLAllocHandle (SQL_HANDLE_STMT, hdbc, & hstmt ) ; c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 9/51
Vytvoření a provedení dotazu Přímé provedení dotazu SQLCHARquery [ ] = "INSERT INTO... " ; SQLExecDirect ( hstmt, query, SQL_NTS ) ; Připravený dotaz SQLCHAR query = "SELECT jmeno FROM uziv WHERE l o g i n =? " ; SQLPrepare ( hstmt, query, SQL_NTS ) ; SQLBindParameter ( hstmt, 1,... ) ; SQLExecute ( hstmt ) ; c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 10/51
Získání výsledku / / Svazani promennych s vysledkem dotazu SQLCHAR jmeno [ 3 0 ] ; SQLINTEGER jmeno_ind ; SQLBindCol ( hstmt, 1, SQL_C_CHAR, jmeno, sizeof ( jmeno ), & jmeno_ind ) ; / / Ct eni vysledku while ( SQLFetch ( hstmt )! = SQL_NO_DATA ) { i f ( jmeno_ind! = SQL_NULL_DATA ) cout < < jmeno ; } c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 11/51
Odpojení od zdroje dat / / Uvolneni zastupce prikazu SQLFreeHandle (SQL_HANDLE_STMT, hstmt ) ; / / Odpojeni od databaze SQLDisconnect ( hdbc ) ; / / Uvolneni zastupce prikazu SQLFreeHandle (SQL_HANDLE_DBC, hdbc ) ; / / Uvolneni zastupce p r o s t r e d i SQLFreeHandle (SQL_HANDLE_ENV, henv ) ; c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 12/51
Rozhraní pro unifikovaný přístup k datům. Použití i mimo klient-server SŘBD data ve formě tabulek (CSV, XLS,...) Ovladače jsou k dispozici pro většinu databázových systémů. Inspirováno rozhraním ODBC objektové rozhraní, možnost spolupráce s ODBC. c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 13/51
Architektura JDBC c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 14/51
Architektura JDBC c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 15/51
JDBC ovladač 5. Datová vrstva informačních systémů Zprostředkování komunikace aplikace s konkrétním typem databáze. Implementován obvykle výrobcem databáze. Dotazovací jazyk SQL, provedení dotazu: předá se databázi, ovladač vyhodnotí dotaz přímo. Reprezentován specifickou třidou: sun.jdbc.odbc.jdbcodbcdriver, com.mysql.jdbc.driver. c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 16/51
Typy JDBC ovladač Typ 1: využívá ODBC (přes JDBC-ODBC bridge), obtížně konfigurovatelné. Typ 2: komunikace s nativním ovladačem. Typ 3: komunikuje s centrálním serverem (Network Server) sít ovým protokolem, pro rozsáhlé heterogenní systémy. Typ 4: založen čistě na jazyce Java, přímý přístup do databáze. c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 17/51
Registrace ovladače Máme dvě alternativy registrace ovladače: Konkretní ovladač je pevně spojen s aplikací new com.mysql.jdbc.driver() Výběr ovladače za běhu aplikace S t r i n g drivername = "com. mysql. jdbc. D r i v e r " ; t r y { Class. forname ( drivername ) ; } catch ( ClassNotFoundExceptione ) { / / obsluha vyjimky } c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 18/51
Identifikace spojení Identifikace spojení: jdbc:[drivertype]:[database] Příklad: jdbc:mysql://localhost/tis?user=tis &password=tis &useunicode=true &characterencoding=iso-8859-2 c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 19/51
Připojení k databázi Connection con = DriverManager.getConnection( url_string, user_string, password_string ); Postup: 1 DriverManager se dotáže všech registrovaných ovladačů. 2 Rozpozná-li ovladač své url, vrátí objekt Connection. c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 20/51
Objekt Statement Reprezentuje SQL příkaz, třídy: Statement PreparedStatement CallableStatement Vytvoření instance: Statement stmt= con.createstatement(); Provedení příkazu: ResultSet rs= stmt.executequery( "SELECT * FROM t"); int num = stmt.executeupdate( "DELETE * FROM t"); c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 21/51
Objekt ResultSet Reprezentuje výsledek dotazu SELECT: Statement stmt = con. createstatement ( ) ; ResultSet r s = stmt. executequery ( "SELECT FROM u z i v a t e l " ) ; while ( rs. next ( ) ) { S t r i n g l o g i n = rs. g e t S t r i n g ( " l o g i n " ) ; S t r i n g jmeno = rs. g e t S t r i n g ( " jmeno " ) ; } rs. close ( ) ; stmt. close ( ) ; c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 22/51
Ošetření chyb 5. Datová vrstva informačních systémů public class SQLException extends Exception t r y {... } catch ( SQLException e ) { while ( e! = null ) { System. out. p r i n t l n ( e. getmessage ( ) ) ; System. out. p r i n t l n ( e. getsqlstate ( ) ) ; System. out. p r i n t l n ( e. geterrorcode ( ) ) ; e = e. getnextexception ( ) ; } } c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 23/51
Parametrizované příkazy Možnost předkompilace opakované provedení příkazu. Bezpečnější než konkatenace řetězců. Parametry označené znakem?, indexované od 1, INSERT INTO u z i v a t e l ( l o g i n, jmeno ) VALUES(?,? ) c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 24/51
Parametrizované příkazy PreparedStatement pstmt = con. preparestatement ( "INSERT... VALUES(?,? ) " ) ; pstmt. clearparameters ( ) ; pstmt. s e t S t r i n g ( 1, " wal007 " ) ; pstmt. s e t N u l l ( 2, Types.VARCHAR) ; c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 25/51
Příklad, Oracle 1/2 DriverManager. r e g i s t e r D r i v e r (new OracleDriver ( ) ) ; S t r i n g connstr = " jdbc : oracle : t h i n : @infra. cs. vsb. cz " + " :1521: d456 " ; Connection connection = DriverManager. getconnection ( connstr, " xxx ", " yyy " ) ; Statement statement = connection. createstatement ( ) ; boolean r e s u l t f = statement. execute ( "UPDATE PROBE_SET VALUE=1 WHERE ID = 2 " ) ; c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 26/51
Příklad, Oracle 2/2 ResultSet r e s u l t S e t = null ; i f ( r e s u l t f ) { r e s u l t S e t = statement. getresultset ( ) ; } i n t updatecount = statement. getupdatecount ( ) ; statement. close ( ) ; connection. close ( ) ; c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 27/51
Příklad - JSTL 5. Datová vrstva informačních systémů Definice datového zdroje v JSTL. < s q l : setdatasource var= " datasource " d r i v e r = " org. g j t.mm. mysql. d r i v e r " u r l = " jdbc : mysql : / / l o c a l h o s t / db " user= " guest " password= " guest " / > < s q l : query datasource= " $ { datasource } "... / > c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 28/51
ADO.NET 5. Datová vrstva informačních systémů Přístup k datům na platformě.net. Možnost práce s XML daty. Propojení na další komponenty.net. c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 29/51
Architektura ADO.NET 1/2 Komponenty zaměřené na obsah: DataSet objekt v paměti obsahující data z datového zdroje, DataTable, DataRow, DataColumn reprezentace tabulky, záznamu a atributu. DataRelation vytvoření vazby mezi dvěma instancemi DataSet definováním vazebního atributu DataColumn. c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 30/51
Architektura ADO.NET 2/2 Komponenty pro správu Connection reprezentuje spojení k SŘBD, Command příkaz nad vytvořeným spojením, DataReader získání výsledku dotazu, DataAdapter objekt mezi DataSet a datovým zdrojem. Úkolem je naplnit DataSet a aktualizovat datový zdroj. c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 31/51
Architektura ADO.NET c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 32/51
Komponenty ADO.NET DataReader rychlý přístup k datům, pouze čtení směrem vpřed. DataSet obsahuje kopii dat z datového zdroje, čtení a zápis dat a schématu ve formátu XML. DataAdapter abstrakce přípojení a příkazu, naplnění a synchronizace dat pro DataSet. c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 33/51
Příklad, Oracle 1/3 using System. Data ; using System. Data. O r a c l e C l i e n t ;... OracleConnection connection = new OracleConnection ( " Data Source= i n f o ; User ID=xxx ; Password=yyy " ) ; connection. Open ( ) ; OracleCommand command = new OracleCommand ( " s e l e c t from student ", connection ) ; OracleDataAdapter dbadapter = new OracleDataAdapter ( command ) ; DataSet dataset = new DataSet ( " student " ) ; c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 34/51
Příklad, Oracle 2/3 t r y { dbadapter. F i l l ( dataset ) ; } catch ( Exception exc ) { throw new Exception ( exc. Message ) ; }.... c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 35/51
Příklad, Oracle 3/3.... / / draw the r e s u l t System. Windows. Forms. DataGrid studentdatagrid = new System. Windows. Forms. DataGrid ( ) ; studentdatagrid. DataSource = dataset ; studentdatagrid. Update ( ) ;... connection. Close ( ) ; c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 36/51
ASP.NET, příklad AspNetExampleApp 1/3 CREATE TABLE PaperVersion_ test ( i d INT NOT NULL PRIMARY KEY IDENTITY, date DATETIME NOT NULL, i d F i l e T y p e INT REFERENCES FileType ) ; CREATE INDEX PaperVersion_ id ON PaperVersion_ test ( i d ) ; CREATE TABLE F i l e T y p e _ t e s t ( i d INT NOT NULL PRIMARY KEY IDENTITY, extension VARCHAR( 5 ) NOT NULL, mime VARCHAR( 2 0 ) NOT NULL ) ; CREATE INDEX FileType_id ON F i l e T y p e _ t e s t ( i d ) ; INSERT INTO F i l e T y p e _ t e s t Values ( pdf, a p p l i c a t i o n / pdf ) ;... INSERT INTO PaperVersion_test Values ( 2/12/2008, 1 ) ;... c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 37/51
ASP.NET, příklad 2/3 Příklad: AspNetExampleApp, Default.aspx c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 38/51
ASP.NET, příklad 3/3 <%@ Page Language= "C# " AutoEventWireup= " t r u e " CodeBehind= " D e f a u l t. aspx. cs " I n h e r i t s = " AspNetExampleApp. _Default " %> <html xmlns= " h t t p : / / www. w3. org /1999/ xhtml " > <body><form i d = " form1 " runat=" server " > <asp : DropDownList ID= " DropDownList1 " runat=" server " DataSourceID= " SDS_FileType " DataTextField=" extension " DataValueField= " i d " > < / asp : DropDownList> <asp : SqlDataSource ID= " SDS_FileType " runat=" server " ConnectionString="<%$ ConnectionStrings : ConnectionString %> SelectCommand= "SELECT FROM [ F i l e T y p e _ t e s t ] " > < / asp : SqlDataSource> < / form>< / body>< / html> c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 39/51
Datová vrstva a bezpečnost - SQL Injection 1/2 Mějme dotaz: S t r i n g s t r = "SELECT uniqueid FROM user WHERE username = " + username + " AND password = " + password + " ; " ; Pokud username=" or 1=1 --", pak: SELECT uniqueid FROM user WHERE username= OR 1=1 AND password = heslo Získáme jedinečná čísla všech uživatelů. http://portal.gov.cz/ukaz.php?id=1.../ukaz.php?id=1 %20OR%201=1%20-- c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 40/51
Datová vrstva a bezpečnost - SQL Injection 2/2 Mějme dotaz: S t r i n g s t r = "SELECT uniqueid, email FROM uziv WHERE username = " + username " " ; Pokud username=" or a = a", pak: SELECT uniqueid, email FROM u z i v WHERE username = or a = a Získáme jedinečná čísla všech uživatelů. c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 41/51
Obrana proti SQL Injection Testování hodnot datových typů, např. nahrazení apostrofu dvěma apostrofy. Použít parametrizované SQL příkazy: S t r i n g strquery = "SELECT uniqueid FROM users WHERE username=@username AND password=@password " ; V případě JDBC pak použijeme pro vytvoření dotazu třídy SqlCommand a SqlParameter. Využíváme uložených procedur. c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 42/51
SQL Injection, Reference http://www.security-portal.cz/sql-injection.html http://packetstormsecurity.org/papers/bypass/ sql-injection.html http://en.wikipedia.org/wiki/sql_injection c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 43/51
Transakce, JDBC 1/2 Implicitně je v JDBC každý zaslaný příkaz proveden jako samostatná transakce. Pokud chceme více příkazu provést v jedné transakci musíme nastavit autocommit na false. c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 44/51
Transakce, JDBC 2/2 / / p r i k a z y jsou potvrzeny az zaslanim commit con. setautocommit ( false ) ; t r y { PreparedStatement updatesales = con. preparestatement ( "UPDATE COFFEES SET SALES =? WHERE COF_NAME LIKE? " ) ; / / nastaveni parametru updatesales. executeupdate ( ) ; PreparedStatement updatetotal = con. preparestatement ( "UPDATE COFFEES SET TOTAL = TOTAL +? WHERE NAME LIKE? " ) ; / / nastaveni parametru updatetotal. executeupdate ( ) ; con. commit ( ) ; / / p o t v r z e n i prikazu } catch ( SQLExceptione ) { con. r o l l b a c k ( ) ; } / / obnoveni stavu pred zacatkem transakce con. setautocommit ( true ) ; c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 45/51
Transakce, ADO.NET 1/2 t r y { Connect ( ) ; / / nastaveni mconnection SqlTransaction SqlTransaction = mconnection. BeginTransaction ( I s o l a t i o n L e v e l. S e r i a l i z a b l e ) ; / / prepare the f i r s t i n s e r t command... SqlCommand command = new SqlCommand ( null, mconnection, s q l T r a n s a c t i o n ) ; i n t insertno = command. ExecuteNonQuery ( ) ; / / prepare the second update command i n t updateno = command. ExecuteNonQuery ( ) ; } msqltransaction. Commit ( ) ; mconnection. Close ( ) ; c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 46/51
Transakce, ADO.NET 2/2 catch ( Exception e ) { msqltransaction. Rollback ( ) ; mconnection. Close ( ) ; throw e ; } c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 47/51
Využití objektově-relačního modelu 1/2 Ukázka Oracle Spatial - rozšíření Oracle pro uložení prostorových dat. Prostorový atribut (např. tvar budovy) je uložen v atributu typu: SDO_GEOMETRY. Ukázka: Vložení záznamu do tabulky LayerBuilding s prostorovým atributem shape. OracleCommand command = mdatabase. CreateCommand ( ) ; S t r i n g INSERT = "INSERT INTO LayerBuilding ( " + " objid, id, f i d, area, shape ) " + " VALUES ( : objid, : id, : f i d, : area, " ; c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 48/51
Využití objektově-relačního modelu 2/2 S t r i n g shape = "SDO_GEOMETRY(2003, " + " 2065, NULL, SDO_ELEM_INFO_ARRAY(1,1003,1), " + "SDO_ORDINATE_ARRAY( " ; command. CommandText = INSERT + shape + strpolygon + " ) ) ) " ; OracleParameter objidparam = new OracleParameter ( " o b j I d ", OracleDbType. Varchar2, 1 2 8 ) ; objidparam. Value = l a y e r B u i l d i n g. ObjId ; command. Parameters. Add ( objidparam ) ;... c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 49/51
Implementace přístupu k databázi Implementace objektového rozhraní k relační databázi, tzv: objektově-relační mapování: Pro každý záznam a tabulku vytvoříme třídu, např. Student a StudentTable. Vhodné je automatické generování z SQL skriptu Viz příklad AspNetExampleApp, TableRelForm.aspx Můžeme využít rámec, tvořící mezivrstvu mezi aplikací a JDBC/ADO.NET ovladačem: Hibernate, http://www.hibernate.org/ c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 50/51
Reference 5. Datová vrstva informačních systémů ODBC http://www.microsoft.com/data/odbc/ http://www.unixodbc.org/ JDBC http://java.sun.com/products/jdbc ADO.NET http://www.msdn.com/ c 2006-2008 Michal Krátký, Miroslav Beneš Tvorba informačních systémů 51/51