Bazy danych Paweł Kasprowski pawel@kasprowski.pl
Łączenie z bazą danych Sterownik Protokół komunikacyjny Adres serwera Port nasłuchowy Przesłanie zapytania SQL Odebranie rezultatów
Pierwszy przykład JDBC import java.sql.*; class DBExample1{ public static void main(string[] args){ try{ Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connection con = DriverManager.getConnection("jdbc:odbc:uran","lab","lab"); Statement stmt = con.createstatement(); ResultSet rs = stmt.executequery("select * from pracownicy"); while(rs.next()) System.out.print(rs.getString(1)+" "+rs.getstring(4)+"\n"); con.close(); catch(sqlexception ec) { System.err.println(ec.getMessage()); catch(classnotfoundexception ex) {System.err.println("Cannot find driver."); DBExample1.java
Ładowanie sterownika Zwykle sterownik typu 4 Ściągnięcie pliku jar ze sterownikiem Umieszczenie go na ścieżce Zmiana nazwy sterownika i url'a w programie
Przykłady sterowników SQL Server 2005 (http://msdn.microsoft.com/data/ref/jdbc) java -classpath ".;msbase.jar;mssqlserver.jar;msutil.jar" %1 MySQL (http://www.mysql.com/products/connector/j/) java -classpath ".;mysql-connector-java.jar" %1 PostgreSQL (http://jdbc.postgresql.org) java -classpath ".;postgres-8.2dev-503.jdbc2ee.jar" %1 run.bat
Zmiana sterownika import java.sql.*; class DBExample1{ public static void main(string[] args){ try{ Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connection con = DriverManager.getConnection("jdbc:odbc:uran","lab","lab"); Statement stmt = con.createstatement(); ResultSet rs = stmt.executequery("select * from pracownicy"); while(rs.next()) System.out.print(rs.getString(1)+" "+rs.getstring(4)+"\n"); con.close(); catch(sqlexception ec) { System.err.println(ec.getMessage()); catch(classnotfoundexception ex) {System.err.println("Cannot find driver."); DBExample1.java
Zmiana sterownika import java.sql.*; class DBExample1{ public static void main(string[] args){ try{ Class.forName("com.mysql.jdbc.Driver"); Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1/baza","lab","lab"); Statement stmt = con.createstatement(); ResultSet rs = stmt.executequery("select * from pracownicy"); while(rs.next()) System.out.print(rs.getString(1)+" "+rs.getstring(4)+"\n"); con.close(); catch(sqlexception ec) { System.err.println(ec.getMessage()); catch(classnotfoundexception ex) {System.err.println("Cannot find driver."); DBExample1.java
Utrzymywanie połączenia Nawiązanie połączenia jest czasochłonne lepiej więc raz nawiązane połączenie używać do kolejnych zapytań Problem: jak przechwać informację o połączeniu, jeśli jest ono używane w różnych obiektach Rozwiązanie: własny obiekt "Połączenie" dostępny globalnie (wszędzie w aplikacji) Pytanie: jak to zrobić? Rozwiązanie naiwne: przekazywanie referencji na obiekt do każdej klasy w dużych aplikacjach niemożliwe
Użycie funkcji statycznych Funkcja lub właściwość statyczna: istnieje (i jest dostępna!) niezależnie od obiektów Dostęp do niej z innego obiektu przez nazwę istniejącego obiektu lub nazwę klasy
Static members class Foo{ int x;...... Foo f1=new Foo(); Foo f2=new Foo(); f1.x=1; f2.x=2; println(f1.x+, +f2.x); class Foo{ static int x;...... Foo f1=new Foo(); Foo f2=new Foo(); f1.x=1; f2.x=2; println(f1.x+, +f2.x); 1,2 2,2
Static members class Foo{ int x;...... Foo f1=new Foo(); Foo f2=new Foo(); f1.x=1; f2.x=2; println(f1.x+, +f2.x); 1,2 class Foo{ static int x;...... Foo f1=new Foo(); Foo f2=new Foo(); f1.x=1; f2.x=2; Foo.x=10; println(f1.x+, +f2.x); 10,10
Dostęp do elementów statycznych class Foo{ private static String x; public static String getx() {return x; Dowolna klasa ma dostęp do x:... String mojazmienna = Foo.getX();...
Inicjalizacja zmiennej class Foo{ private static String x; public static String getx() { if(x==null) x="abcd"; return x;
Zmienna jako obiekt import java.sql.*; class DBCon { private static Connection con; public static Connection getconnection() { if(con==null) {... return con; W programie: Connection con = DBCon.getConnection();...
Inicjalizacja połączenia import java.sql.*; class DBCon { private static Connection con; static Connection getconnection() { if(con==null) { try{ Class.forName("..."); con = DriverManager.getConnection("<url>", "...","..."); catch(sqlexception ec) {... catch(classnotfoundexception ex) {... return con;
Użycie DBCon... Connection c = DBCon.getConnection(); try{ Statement stmt = c.createstatement(); ResultSet rs = stmt.executequery("..."); while(rs.next()) System.out.println(rs.getString(1)); catch(sqlexception ec) {......
Użycie DBCon... try{ Statement stmt = DBCon.getConnection().createStatement(); ResultSet rs = stmt.executequery("..."); while(rs.next()) System.out.println(rs.getString(1)); catch(sqlexception ec) {......
Zalety rozwiązania Połączenie nawiązywane jest tylko raz na początku Kolejne wywołania używają już stworzonego połączenia Wada: program główny niezbyt się uprościł Rozwiązanie: może więcej logiki do DBCon?
Uproszczenie aplikacji try{ ResultSet rs = DBCon.getDBCon().executeQuery("select..."); while(rs.next()) System.out.println(rs.getString(1)); catch(sqlexception ec) {...
DBCon część statyczna class DBCon { private static DBCon dbcon; static DBCon getdbcon() { if(dbcon==null) dbcon = new DBCon(); return dbcon;...
DBCon konstruktor class DBCon {... private Connection con; public DBCon() { try{ Class.forName("..."); con = DriverManager.getConnection(".",".","."); catch(sqlexception ec) {... catch(classnotfoundexception ex) {......
DBCon executequery class DBCon {... public ResultSet executequery(string query) { ResultSet rs = null; try{ Statement stmt = con.createstatement(); rs = stmt.executequery(query); catch(sqlexception ec) {... return rs;
Zalety i wady rozwiązania Aplikacja niezależna od źródła danych Wszelkie zmiany w dostępie do danych w jednym miejscu Wada: wciąż obsługa ResultSet'a w programie głównym
JOptionPane Prekonfigurowane okna dialogowe (4 typy) showmessagedialog(...); Pokazuje informacje i przycisk OK showconfirmdialog(...) Pyta o potwierdzenie (Yes/No/Cancel) showinputdialog(...) Pobiera jakąś wartość showoptiondialog(...) Mocno konfigurowalne okno dialogowe
Przykład JOptionPane [1] Zwykła informacja JOptionPane.showMessageDialog(frame,"That s a message");
JOptionPane example [2] Proste okno potwierdzenia int answer = JOptionPane.showConfirmDialog(frame, "Choose Yes or No", "Title", JOptionPane.YES_NO_OPTION);
JOptionPane example [3] Wprowadzanie danych ImageIcon icon = new ImageIcon("duke.gif"); String s = (String)JOptionPane.showInputDialog( frame, "Complete the sentence:\n"+ "\ I love...\"", "Customized Dialog", JOptionPane.PLAIN_MESSAGE, icon, null, cats");
JOptionPane example [4] Input values with list of choices Object[] possibilities = { cats", dogs", bats"; String s = (String)JOptionPane.showInputDialog( frame, "Complete the sentence:\n"+ "\ I love...\"", "Customized Dialog", JOptionPane.PLAIN_MESSAGE, icon, possibilities, cats");
JOptionPane example [5] Własne przyciski typu Yes/No/Cancel Object[] options = { First", Second", Forget it!"; int answer = JOptionPane.showOptionDialog(frame, What s your choice?, Title", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[2]);
Parametry JOptionPane.showXX parentwindow message messagetype optiontype options icon title initialvalue
messagetype ERROR_MESSAGE INFORMATION_MESSAGE WARNING_MESSAGE QUESTION_MESSAGE PLAIN_MESSAGE
optiontype DEFAULT_OPTION YES_NO_OPTION YES_NO_CANCEL_OPTION OK_CANCEL_OPTION Możliwości te mogą zostać rozszerzone lub zmienione przez użycie parametru options
Zwracane wartości Integer: YES_OPTION, NO_OPTION, CANCEL_OPTION, OK_OPTION, CLOSED_OPTION. String: wprowadzona wartość DialogDemo
Wstawianie tablic i list Wyświetlanie danych: JTable JList Przechowywanie danych: TableModel ListModel
Przykładowa tablica Vector colnames = new Vector(); colnames.add( first"); colnames.add( second"); colnames.add("third"); DefaultTableModel tbmod = new DefaultTableModel(colnames,0); for(int i=0;i<10;i++) { Vector row = new Vector(); row.add( row +String.valueOf(i)); row.add( val2"); row.add( val3"); tbmod.addrow(row); JTable tbl = new JTable(tbMod); contentpane.add(new JScrollPane(tbl)); FirstTable.java
Własny model danych class MyFirstTableModel extends AbstractTableModel { public int getrowcount() {... public int getcolumncount() {... public String getcolumnname(int Col) {... public Object getvalueat(int nrow, int ncol) {... dowolny sposób przechowywania dowolnych danych
Przykład modelu danych class MyFirstTableModel extends AbstractTableModel { Vector data; Vector cols; public MyFirstTableModel(Vector p_cols) { cols = p_cols; data = new Vector(); public void addrow(vector p_row) { data.add(p_row); public int getrowcount() { return data.size(); public int getcolumncount() { return cols.size(); public Object getvalueat(int nrow, int ncol) { return ((Vector)data.get(nRow)).get(nCol);
Użycie modelu danych Vector tbcols = new Vector(); tbcols.add("jeden"); tbcols.add("dwa"); MyFirstTableModel tbmod = new MyFirstTableModel(tbCols); for(int i=0;i<10;i++) { Vector row = new Vector(); row.add(string.valueof(i)+"x"); row.add("y"); tbmod.addrow(row); JTable tbl = new JTable(tbMod); contentpane.add(new JScrollPane(tbl)); FirstTable2.java
Wyświetlanie informacji z bazy... DbTableModel tbm = new DbTableModel("select * from table"); JTable tbl = new JTable(tbm);... DBTable.java
Definicja DbTableModel class DbTableModel extends AbstractTableModel {... public DbTableModel(String query) {... Statement stmt = con.createstatement(); ResultSet rs = stmt.executequery(query);... cols = new Vector(); for (int i=1;i<=noofrows;i++) cols.add(rs.getmetadata().getcolumnname(i)); while(rs.next()) { Vector row = new Vector(); for (int i=1;i<=noofrows;i++) row.add(rs.getstring(i)); data.add(row);...
Mapowanie obiektowe ORM: Object-to-Relational Mapping Idea: jednolitość interfejsu obiektowego Użycie obiektów zamiast ResultSet'ów Jak najmniej SQLa jak najwięcej programowania obiektowego Zwykle wiersz zapytania to obiekt w programie Na przykład funkcja: getpracownicy(int idzesp) mogłaby zwracać listę obiektów klasy Pracownicy
Bean Pracownik class Pracownik { int nrp; String nazw; Date dataur; public String getnrp() {return nrp; public void setnrp(int nrp) {this.nrp = nrp; public String getnazw() {return nazw; public void setnazw(string nazw) {this.nazw=nazw; public Date getdataur() {return dataur; public void setdataur(date dataur) {this.dataur=dataur;
Biblioteka Hibernate Biblioteka dla Javy zapewniająca ORM Dostęp do danych przez specjalne klasy Nie wymaga znajomości SQL Konfiguracja w pliku XML hibernate.cfg.xml Każde mapowanie opisane w osobnym pliku: Nazwa.hbm.xml
Klasa przykładowa public class HibernateExample { private final static SessionFactory factory; static { // 1. Inicjalizacja Hibernate Configuration cfg = new Configuration().configure(); // 2. Utworzenie fabryki sesji Hibernate factory = cfg.buildsessionfactory(); public static void main(string[] args) { HibernateExample m = new HibernateExample(); m.createusers(); m.displayusers(); źródło: jlaskowski.blogspot.com
Przykład użycia public void createusers() { // 3. Otwarcie sesji Hibernate Session session = factory.opensession(); // 4. Rozpoczęcie transakcji Transaction tx = session.begintransaction(); // 5. Utworzenie użytkownika User u = new User(); u.setimie("jacek"); u.setnazwisko("laskowski"); // 6. Zapisanie użytkownika w bazie danych session.save(u); // 7. Zatwierdzenie transakcji tx.commit(); // 8. Zamknięcie sesji Hibernate session.close();
Przykład użycia public void displayusers() { // 3. Otwarcie sesji Hibernate Session session = factory.opensession(); // 4. Rozpoczęcie transakcji Transaction tx = session.begintransaction(); // 5. Utworzenie zapytania SQL do bazy o listę użytkowników Criteria criteria = session.createcriteria(user.class); // 6. Wykonanie zapytania SQL List users = criteria.list(); // 7. Iterowanie po wyniku zapytania SQL for (Iterator it = users.iterator(); it.hasnext();) { User user = (User) it.next(); System.out.println(user); // 8. Zatwierdzenie transakcji tx.commit(); // 9. Zamknięcie sesji Hibernate session.close();
Koniec Główne źródło: http://www.java.com/ http://www.hibernate.org/