Technologia Programowania 2016/2017 Wykªad 12 JDBC + Jakub Lemiesz
Stawiamy serwer bazy danych: Derby To, o czym b dziemy mówi, dotyczy praktycznie wszystkich systemów bazodanowych (MySql, SQL Server) Apache Derby system bazodanowy napisana w Java o maªych wymaganiach systemowych (np. urz dzenia mobilne) Mo»e pracowa jako niezale»ny proces (serwer) oraz w trybie wbudowanym (embedded), w ramach tej samej JVM bez odpalania osobnego procesu Pobieramy, odpalamy skrypty konguruj ce i serwer bazy danych na wybranym porcie (w razie problemów: help): E:\derby\bin > set.bat E:\derby\bin > startnetworkserver.bat p 3000 2 / 30
Tryb serwera a tryb wbudowany 3 / 30
JDBC Java DataBase Connectivity JDBC interfejs standaryzuj cy dost p do relacyjnych baz danych dla aplikacji Java Nale»y jedynie dostarczy sterownik do wybranego systemu danych zgodny z tym interfejsem (np. derby.jar, sqlserverjdbc.jar) //DriverManager sam poszuka pasuj cego sterownika //na podstawie podanego adresu String addr = "jdbc:derby://localhost:3000/kubadb"; Connection conn = DriverManager.getConnection(addr); Statement s = conn.createstatement(); 4 / 30
JDBC podstawowe metody Statement s = conn.createstatement(); s.execute("create table..."); s.executeupdate("insert..."); conn.commit(); ResultSet rs = s.executequery("select * from. while(rs.next()) System.out.println(rs.getInt(1)); 5 / 30
JDBC podstawowe metody 1 ResultSet reprezentuje zbiór wierszy zwracanych przez metod executequery(...). ResultSet ma kursor wskazuj cy aktualnie przetwarzany rekord, przesuwany przez next() 2 s.execute(...) zwraca true gdy pierwszy obiekt zwrócony przez zapytanie jest typu ResultSet. Gdy zapytanie zwraca kilka ResultSet przetwarzanie w p tli s.getresultset(). U»ywa si te» do operacji CREATE, DROP. 3 s.executeupdate(); u»ywa si do operacji INSERT, DELETE i UPDATE. Zwraca int liczb wierszy, na które zapytanie miaªo wpªyw. 6 / 30
Przebieg komunikacji w JDBC 7 / 30
PreparedStatement // add many rows by using // predefined statement with parameters String sql = "insert into jdbc_student values (?,?)" PreparedStatement ps = conn.preparestatement(sql); ps.setint(1, 193456); ps.setstring(2, "Jan Kowalski"); ps.executeupdate(); ps.setint(1, 191111); ps.setstring(2, "Anna Nowak"); ps.executeupdate(); 8 / 30
Przykªad u»ycia JDBC 1 Uruchamiamy aplikacj _JDBC_TEST (w trybie debuggowania) 2 Dodatkowo do podgl du zmian na serwerze bazy dany uruchamiamy program SQuirreL SQL Client 3 SQuirreL SQL Client program na licencji GNU, umo»liwia interaktywny dost p do dowolnej bazy (opiera si na JDBC, potrzebuje sterownika *.jar) 9 / 30
Co to jest mapowanie obiektowo-relacyjne? 1 Znaczna cze± tworzonych obecnie aplikacji jest zorientowana obiektowo 2 Dane typowo przechowuje si w relacyjnych bazach danych 3 Mapowanie obiektowo-relacyjne to autmatyczne konwertowanie danych relacyjnych na obiekty (i obiektów na dane relacyjne) 4 Czy czyste JDBC wystarczy? 10 / 30
Problemy z JDBC, czyli po co nam ORM? Mam program obiektowy i chce stworzy dla niego schemat bazy danych. Mam r cznie pisa SQL?? 1 R cznie ustala typy odwzorowuj ce pola klas? 2 R cznie deniowa powi zania 1:1, 1:m, m:n? (klucze, klucze obce, tabele z powi zaniami) 3 ledzi zmiany w obiektach? Wygodnie by byªo,»eby zmiany w bazie byªy automatyczne... (najlepiej we wszystkich powi zanych tabelach) 11 / 30
Problemy z JDBC, czyli po co nam ORM? 4 Tworzy skomplikowane zapytania? Np. 3 x join: SELECT * FROM Bill b WHERE b.client.addr.city=... 5 Wyniki zapyta«r cznie tªumaczy na obiekty i pola? W czystym JDBC dostajemy ResultSet. R cznie obrabia wiersz po wierszu, pole po polu? (a jak mamy baze 40 tabel, ka»da 20 kolumn?) ORM pobiera powi zane dane automatycznie: Query query = session.createquery("from Student WHERE.. List<Student> studentlist = query.list(); studentlist.get(0).getlectures().get(0).getname(); 12 / 30
Systemy ORM (Red Hat, Inc.) N (dla.net) EclipseLink TopLink (Oracle)... Java Persistence API (JPA) standard ORM dla Java. Du»y wpªyw na jego ksztaªt miaª. Wªasny system ORM? (patrz: ksi»ka Larmana) 13 / 30
Popularnosc systemów ORM - ¹ródªo 14 / 30
Uruchamianie aplikacji z Instalacja : ªatwo przez Maven'a i pom.xml Konguracja pliku hibernate.cfg.xml hibernate.cfg.xml <property name="connection.driver_class"> org.apache.derby.jdbc.clientdriver </property> <property name="connection.url"> jdbc:derby://localhost:3000/kubadb </property> <mapping class="student" /> <mapping class="examresult" /> <mapping class="scholarship" /> <mapping class="lecture" /> 15 / 30
Co robi nasza aplikacja? (projekt TEST) 16 / 30
U»ywanie dopisujemy adnotacje @Column i walidacja pól @Column(name = SEX) @Pattern(regexp = F M) private String sex; 17 / 30
U»ywanie dopisujemy adnotacje @OneToMany, @ManyToOne, @ManyToMany 18 / 30
@MappedSuperclass public class PersonObject { @Id GeneratedValue(strategy=GenerationType.AUTO) @Column(name="index") private int id;... @MappedSuperclass public class Person extends PersonObject { Column(name="NAME") private String name; @Column(name = "AGE") @Min(0) @Max(99) private int age; 19 / 30
@Entity @Table(name="Student") public class Student extends Person { @Transient private String poleniedobazy; @OneToOne(fetch = FetchType.LAZY, mappedby="grantedto") private Scholarship scholarship; @OneToMany(cascade = CascadeType.ALL, mappedby="student") private List<ExamResult> examresults; @ManyToMany(mappedBy = "students") private List<Lecture> lectures; 20 / 30
Po koleji, co robimy? 1 Tworzymy plik konguracyjny w XML, piszemy adnotacje (mamy poª czenie i schemat bazy) 2 SessionFactory w oparciu o plik konf. tworzy sesje 3 Pobieramy sesj z SessionFactory i wykonujemy operacje na obiektach w ramach sesji i w oparciu o transakcje (przykªad na nast pnej stronie) 4 Po co sesja? Po co transakcje? 21 / 30
- przykªadowe u»ycie Session session = getsessionfactory().opensession(); session.begintransaction(); Student student1 = new Student();//obiekt transient student1.setname("zdzisªaw "); session.save(student1);//obiekt persistent Student student2 = new Student(); student2.setname("anna Zdolna"); session.save(student2); session.gettransaction().commit(); session.begintransaction();... session.close(); 22 / 30
Obiekty w stanie Transient (sesja) nic nie wie o obiektach w tym stanie, GC je usuwa gdy nie ma referencji i ±lad po nich ginie Nowo tworzone obiekty, obiekty usuni ty ze bazy Obiekty w stanie Persistent (sesja) 'widzi' obiekty w stanie persistent, wszystkie zmiany w nich s zapisywane do bazy Mog to by obiekty transient na których wykonano operacj save lub obiekty wczytane z bazy Obiekty w stanie Detached Np. obiekty persistent po zamkni ciu sesji (mog by przywrócony do stanu persistent w innej sesji) Jest z nimi zwi zany rekord w bazie, ale nie s zarz dzane przez (zmiany w nich nie s odnotowywane w bazie, mog zosta usuni te przez GC) 23 / 30
Cykl»ycia obiektów w sesji ¹ródªo 24 / 30
Po co jest sesja? 1 Sesja od momentu stworzenia do zamkni cia utrzymuje pojedyncze poª czenie z baz 2 Obiekt w stanie 'persistant' jest zwiazany z jedn sesj (sesja ma persistence context graf obiektów) 3 Zmiany w persistence context s automatycznie przenoszone do bazy metod ush() wywoªywan : r czne przed wykonaniem zapytania do bazy przy commitowaniu transakcji przy zamykaniu sesji 4 Wykonanie 'commit()' jedynie zatwierdza zmiany 25 / 30
Session session1 = SessionFactory.getCurrentSession(); Student student = session1.get(student.class, 1); session1.close(); // `detached' - modification is ignored by student.setname("zenek"); //re-attach the object, returning to`persistent' Session session2 = SessionFactory.getCurrentSession(); session2.update(student); session2.gettransaction().commit(); 26 / 30
commit() vs. ush() przykªad Transaction tran = session.begintransaction(); for ( int i=0; i<1000; i++ ) { session.save( new Student(i,...) ); if ( i % 20 == 0 ) { session.flush(); session.clear(); } } tran.commit(); session.close(); 27 / 30
Zapytania do bazy z u»yciem HQL String hql = "FROM Student S WHERE S.id > 0 ORDER BY S.name DESC"; Query query = session.createquery(hql); List<Student> studentlist = query.list(); println( "Student " + studentlist.get(0).getname() + "jest zapisany na: " + studentlist.get(0).getlectures().get(0).lecturename() ); 28 / 30
Architektura 29 / 30
Dla zainteresowanych tematem polecam 30 / 30