Datenbank Anbindung Arthur Zaczek Nov 2014 Datenbank Anbindung 1 Datenbank Anbindung 1.1 Übersicht Datenbankanbindung mit JDBC und ADO.NET. 1.2 .NET ADO.NET Kein Treiberkonzept. Jede Datenbank hat eigenes Set an Klassen. Meistens wird für nur eine Datenbank programmiert 1.3 JAVA JDBC Vielzahl an Treibern für versch. Datenbanken. Diese werden durch den DriverManager verwaltet. Programmierung ist aus Sicht der Klassen Datenbank unabhängig. 1.4 Ausblick Datenbanksysteme unterscheiden sich im Detail. Generische Routinen sind nur schwer selbst zu realisieren. Daher: ORM benutzen. • (n)Hibernate (Java & .NET) • EntityFramework (.NET) • (Linq2SQL) 2 Java & MSSQL 2.1 Vorbereitungen Anbindung an einen SQL Server (Express) 1. 2. 3. 4. 5. 6. 7. SQL Server Express vorbereiten TCP/IP Verbindungen zulassen SQL Server Browser starten SQL User anlegen JDBC Treiber vorbereiten JDBC Treiber von msdn.microsoft.com herunterladen & installieren 1 JDBC Treiber dem Projekt hinzufügen 1 http://msdn.microsoft.com/data/jdbc/ 1 Datenbank Anbindung 2.2 Andere Datenbanken • Datenbank vorbereiten • Treiber organisieren 2.3 TCP/IP aktivieren 1. SQL Server Configuration Manager starten 2. SQL Server 2005 Network Configuration 3. TCP/IP einschalten 2.4 SQL Server Browser aktivieren 1. SQL Server Configuration Manager starten 2. SQL Server Services 3. SQL Server Browser starten Alternativ auch über services.msc 2.5 Datenbankuser anlegen JDBC kann sich nicht mit Integrated Authentication (=Windows User) anmelden, daher muss ein Datenbankuser angelegt werden. 2.6 JDBC Treiber vorbereiten 1. JDBC Treiber von msdn.microsoft.com herunterladen & installieren 2 2. CLASSPATH lt. Dokumentation setzen 3. Treiber dem Projekt hinzufügen 3 JDBC 3.1 • • • • • • • Bestandteile JDBC API Schnittstelle zu Datenbanksystemen CRUD Operationen JDBC Driver Manager Verwaltet Datenbank Treiber JDBC-ODBC Bridge ODBC Anbindung mit Java 2 http://msdn.microsoft.com/data/jdbc/ 2 Datenbank Anbindung 3.2 Treiber laden Zuerst muss/müssen der/die Treiber geladen werden. z.B.: MS SQL Server try { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); } catch(ClassNotFoundException ex) { JOptionPane.showMessageDialog(null, "MS JDBC Driver not installed\n" + ex); } 3.3 Verbindung öffnen import java.sql.* Connection db = DriverManager.getConnection( "jdbc:sqlserver://localhost\\sqlexpress;" + "databaseName=Northwind", "java", "java"); 3.4 Verbindung öffnen jdbc:sqlserver:// Auswahl des Treibers lt. Treiberdokumentation Datenbankserver Datenbankname localhost\sqlexpress databaseName=Northwind java/java 3.5 Username/Password als Parameter Objekte Connection PreparedStatement Datenbankverbindung SQL Statement, das ausgeführt werden soll Kann Parameter enthalten Ergebnis eines SELECT Statements SQL Statement OHNE Parameter ResultSet Statement 3.6 CRUD – „R“ // Datenbankverbindung öffnen Connection db = DriverManager.getConnection(...); // SQL STMT vorbereiten PreparedStatement cmd = db.prepareStatement("SELECT[ProductID], [ProductName], ... FROM [Products] WHERE [UnitPrice] > ?"); // Parameter setzen cmd.setDouble(1, 100.0); // Ausführen 3 Datenbank Anbindung ResultSet rd = cmd.executeQuery(); // Daten holen while(rd.next()) { Product p = new Product(); p.setProductID(rd.getInt(1)); p.setProductName(rd.getString(2)); getModel().addElement(p); } 3.7 Nicht vergessen! rd.close(); cmd.close(); db.close(); Auf Exceptionhandling achten! 3.8 ResultSet Das ResultSet selbst kann auch Daten aktualisieren. Dazu muss das ResultSet über das Statement Objekt erzeugt werden, mit einem Updatefähigen Cursor. Bitte nicht verwenden!!! • Cursor binden Datenbankresourcen • Cursor verursachen Table Locks • Die Anzahl der max. User wird unnötig verringert 3.9 CRUD – „CUD“ // Datenbankverbindung öffnen Connection db = DriverManager.getConnection(...); // SQL STMT vorbereiten PreparedStatement cmd = db.prepareStatement("UPDATE [Products] SET [ProductName] = ? WHERE [ProductID] = ?"); // Parameter setzen cmd.setString(1, "I like Schoggi Schokolade"); cmd.setInt(2, 27); // Ausführen, Rows enthält die Anzahl der betroffenen Zeilen int rows = cmd.executeUpdate(); 3.10 Nicht vergessen! cmd.close(); db.close(); 4 Datenbank Anbindung Auf Exceptionhandling achten! 4 4.1 Prepared Statement Motivation (Gilt für JDBC & ADO.NET) Warum sollten sie verwendet werden? z.B.: Datumformat WHERE Date = "2008/01/05" WHERE Date = "2008-05-01" WHERE Date = "01.05.2008" 4.2 SQL Injection Aus einem Programm: String sql = "SELECT * FROM Products WHERE Name = '" + txtName.getText() + "'"; Usereingabe: '; DROP TABLE Products; -SQL Stmt an den Server: SELECT * FROM Products WHERE Name = ''; DROP TABLE Products; --' 4.3 SQL Injection SQL Injection! Ein Benutzer_inn ist in der Lage, das SQL Statement, das an einen Datenbank Server gesendet wird, nach eigenen Wünschen zu manipulieren. Das ist ein sehr häufiger Angriffsvektor. Prepared Statements verhindern SQL Injection zuverlässig 4.4 Prepared Statement Procedure Cache, Execution Plan! Datenbanken (alle) müssen zuerst den SQL String in einen Execution Plan umrechnen. Das Umrechnen kostet Zeit! Schickt man immer wieder den selben SQL String, dann kann sich die Datenbank den Execution Plan merken. = Performancegewinn 5 Datenbank Anbindung 5 ADO.NET 5.1 Überblick Es gibt keine Treiber. Jede Datenbank hat ihre eigenen .NET Klassen, die untereinander nicht kompatibel sind System.Data.SqlClient System.Data.OleDb System.Data.Odbc 5.2 Providermodelle Es gibt Providermodelle z.B.: • Authentifizierung im ASP.NET • WebParts im ASP.NET • etc. Provider sind keine Datenbank-Zugrifftechnologie! 5.3 SqlClient SqlConnection SqlCommand SqlDataReader Datenbankverbindung Sql Statement, mit Parametern Ergebnis eines SELECT Statement Kapselt einen Parameter Datenbanktransaktion SqlParameter SqlTransaction 5.4 DataSet Datasets: • verbrauchen viel Hauptspeicher • sind unhandlich in der Bedienung • eignen sich bestenfalls für Prototypen Auch wenn die Verlockung groß ist (DataGrid, DataAdapter, etc.) – DataSets sind unpraktisch 5.5 Verbindung öffnen using System.Data.SqlClient; 6 Datenbank Anbindung using (SqlConnection db = new SqlConnection(@"Data Source=.\SqlExpress; Initial Catalog=Northwind;Integrated Security=true;")) { db.Open(); ... } 5.6 5.7 Verbindung öffnen Data Source=. . . Initital Catalog=. . . Integrated Security=true Server Datenbank Anmeldung über Windows Identity User Name=User; Password=pass Anmeldung über Username/Password CRUD – „R“ // Datenbankverbindung öffnen using (SqlConnection db = new SqlConnection(...)) { db.Open(); // SQL STMT vorbereiten SqlCommand cmd = new SqlCommand(@"SELECT[ProductID], [ProductName], ... FROM [Products] WHERE [UnitPrice] > @price", db); // Parameter setzen cmd.Parameters.AddWithValue("@price", 100.0); // Ausführen using (SqlDataReader rd = cmd.ExecuteReader()) { // Daten holen while (rd.Read()) { Product p = new Product(); p.ProductID = rd.GetInt32(0); p.ProductName = rd.GetString(1); } } } 5.8 Nicht vergessen! using() { } db.Close(); db.Dispose(); Auf Exceptionhandling achten! 7 Datenbank Anbindung 5.9 CRUD – „CUD“ // Datenbankverbindung öffnen using (SqlConnection db = new SqlConnection(...)) { db.Open(); // SQL STMT vorbereiten SqlCommand cmd = new SqlCommand(@„UPDATE [Products] SET [ProductName] = @n WHERE [ProductID] = @ID", db); // Parameter setzen cmd.Parameters.AddWithValue("@n", "I like Schoggi Schokolade"); cmd.Parameters.AddWithValue("@ID", 27); // Ausführen, rows enthält die Anzahl der betroffenen Zeilen int rows = cmd.ExecuteNonQuery(); } 8