Java Database Connectivity Celem ćwiczenia jest zbudowanie kilku prostych serwletów z użyciem technologii JDBC. Podczas ćwiczenia zbudowane zostaną serwlety ilustrujące podstawowe techniki łączenia się z bazą danych, wykonywania zapytań oraz przetwarzania wyników zapytania. Do wykonania ćwiczenia potrzebne jest zintegrowane środowisko programistyczne NetBeans IDE (do pobrania z http://www.netbeans.org) oraz środowisko J2SE 1.4.2 (lub wyższe). Dodatkowo, potrzebne są sterowniki JDBC do łączenia się z bazą danych Oracle w wersji 10.2 lub 11.1 do pobrania z : http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/index.html 1. Uruchom narzędzie NetBeans IDE 2. Z menu głównego wybierz File New Project. W otwartym okienku kreatora projektu wybierz kategorię Web i typ projektu Web Application. Kliknij przycisk Next >.
3. Podaj nazwę projektu, PSR JDBC. Kliknij przycisk Next>.. Upewnij się, że wybranym serwerem aplikacji jest zagnieżdżony serwer Tomcat 6.0. Skróć ścieżkę aplikacji do postaci /psr-jdbc i zaznacz zgodność kodu źródłowego z Java 5. Kliknij przycisk Finish.. 4. Wybierz z menu Tools Libraries. Kliknij przycisk New Library Jako nazwę biblioteki podaj Oracle-JDBC, jako typ biblioteki podaj Class Libraries. Kliknij przycisk Add JAR/Folder Zaznacz plik ojdbc5.jar i kliknij przycisk Add JAR/Folder Kliknij przycisk OK.
5. W nawigatorze projektu rozwiń gałąź Libraries,, kliknij prawym klawiszem myszy na ikonie Libraries i z menu kontekstowego wybierz opcję Add Library. Znajdź na liście bibliotekę Oracle-JDBC i kliknij przycisk Add Library.
6. Utwórz nowy serwlet i nazwij go JDBCTestServlet. Umieść serwlet w pakiecie psr.servlets. Umieść w serwlecie poniższy kod. Zwróć uwagę na importowane biblioteki oraz sposób zarejestrowania sterownika JDBC. package psr.servlets; import java.io.*; import java.net.*; import javax.servlet.*; import javax.servlet.http.*; import java.sql.*; import oracle.jdbc.*; public class JDBCTestServlet extends HttpServlet { protected void doget(httpservletrequest request, HttpServletResponse response) throws ServletException, IOException { String url = "jdbc:oracle:thin:@oracle-server.edu.wsnhid.pl:1521:orcl"; String username = "scott"; String password = "tiger"; DriverManager.registerDriver( new oracle.jdbc.oracledriver() ); Connection conn = DriverManager.getConnection(url, username, password); DatabaseMetaData dbmetadata = conn.getmetadata(); PrintWriter out = response.getwriter(); out.println("<html><head><title>jdbc meta data</title></head>"); out.println("<body>"); out.println("<h2>database metadata</h2>"); out.println("<ul>"); out.println("<li>database: " + dbmetadata.getdatabaseproductname()); out.println("<li>version: " + dbmetadata.getdatabaseproductversion()); out.println("<li>jdbc version: " + dbmetadata.getjdbcmajorversion() + "." + dbmetadata.getjdbcminorversion()); out.println("<li>sql keywords: " + dbmetadata.getsqlkeywords()); out.println("<li>list of objects"); out.println("<ul>"); ResultSet tabs = dbmetadata.gettables(null,username,null,null); while (tabs.next()) out.println("<li>" + tabs.getstring("table_name") + " <b>" + tabs.getstring("table_type") + "</b>"); out.println("</ul>"); out.println("</ul>"); out.println("</ul>"); out.println("</body>"); out.println("</html>"); out.close(); catch (SQLException ex) { ex.printstacktrace();
7. W następnym zadaniu nauczysz się wykonywać proste zapytania do bazy danych. Zwróć uwagę, że sterownik JDBC można zarejestrować poprzez jawne załadowanie właściwej klasy. Utwórz serwlet JDBCSimpleQueryServlet w pakiecie psr.servlets i umieść w nim poniższy kod package psr.servlets; import java.io.*; import java.net.*; import java.text.*; import java.util.*; import java.sql.*; import javax.servlet.*; import javax.servlet.http.*; import oracle.jdbc.driver.oracledriver; public class JDBCSimpleQueryServlet extends HttpServlet { protected void doget(httpservletrequest request, HttpServletResponse response) throws ServletException, IOException { String url = "jdbc:oracle:thin:@oracle-server.edu.wsnhid.pl:1521:orcl"; String username = "scott"; String password = "tiger"; Class.forName("oracle.jdbc.OracleDriver"); Connection conn = DriverManager.getConnection(url, username, password); Statement stmt = conn.createstatement(); ResultSet rset = stmt.executequery(" SELECT nazwisko,etat,placa_pod,zatrudniony FROM pracownicy"); response.setcontenttype("text/html"); response.setcharacterencoding("windows-1250"); PrintWriter out = response.getwriter(); out.println("<html><head><title>jdbc simple query</title></head>"); out.println("<body><h2>pracownicy</h2>"); out.println("<table border='1'>"); out.println("<tr><th>nazwisko</th><th>etat</th> <th>płaca</th><th>zatrudnienie</th></tr>"); while (rset.next()) { NumberFormat nf = new DecimalFormat("#####.00"); DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE); String nazwisko = rset.getstring("nazwisko"); String etat = rset.getstring(2); float placa_pod = rset.getfloat("placa_pod"); java.util.date zatrudniony = rset.getdate(4); out.println("<tr><td>" + nazwisko + "</td><td>" + etat + "</td> <td>" + nf.format(placa_pod) + "</td> <td>" + df.format(zatrudniony) + "</td></tr>"); out.println("</table></html>"); out.close(); rset.close(); stmt.close(); conn.close(); catch (SQLException ex) { ex.printstacktrace(); catch (ClassNotFoundException ex) { ex.printstacktrace();
8. Kolejne ćwiczenie obrazuje sposób postępowania z wynikiem zapytania. Utwórz serwlet o nazwie JDBCResultSetServlet w pakiecie psr.servlets i umieść w nim poniższy kod. Zwróć uwagę na przekazywanie połączenia, zapytania i wyniku przez sesję. Zauważ, że ładowanie sterownika przeniesiono do metody init(). package psr.servlets; import java.io.*; import java.net.*; import javax.servlet.*; import javax.servlet.http.*; import java.sql.*; import oracle.jdbc.oracledriver; public class JDBCResultSetServlet extends HttpServlet { public void init() throws ServletException { Class.forName("oracle.jdbc.OracleDriver"); catch (ClassNotFoundException ex) { ex.printstacktrace(); protected void doget(httpservletrequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getsession(); String url = "jdbc:oracle:thin:@oracle-server.edu.wsnhid.pl:1521:orcl"; String username = "scott"; String password = "tiger"; response.setcontenttype("text/html"); response.setcharacterencoding("windows-1250"); PrintWriter out = response.getwriter(); out.println("<html><head><title>resultset management</title></head>"); out.println("<body><h2>resultset management</h2>"); Connection conn = (Connection)session.getAttribute("connection"); if (conn == null) { conn = DriverManager.getConnection(url, username, password); session.setattribute("connection", conn); Statement stmt = (Statement)session.getAttribute("statement"); if (stmt == null) { stmt = conn.createstatement(resultset.type_forward_only, ResultSet.CONCUR_READ_ONLY); session.setattribute("statement", stmt); ResultSet rset = (ResultSet)session.getAttribute("query"); if (rset == null) { rset = stmt.executequery("select nazwisko FROM pracownicy"); session.setattribute("query", rset); String action = request.getparameter("action"); if (action == null) rset.next(); else if (action.equals("next") &&!rset.islast()) rset.next(); else if (action.equals("previous") &&!rset.isfirst()) rset.previous(); out.println(rset.getstring("nazwisko") + "<br/>");
out.println("<a href=\"jdbcresultsetservlet?action=previous\"> <<previous</a>"); out.println("<a href=\"jdbcresultsetservlet?action=next\"> next>></a>"); out.println("</body></html>"); out.close(); catch (SQLException ex) { ex.printstacktrace(); 9. Przetestuj działanie serwletu. Czy działa przewijanie kursora do tyłu? Zweryfikuj komunikat w logu serwera. Zmień typ zbioru wynikowego na TYPE_SCROLL_INSENSITIVE i powtórz ćwiczenie. 10. Celem kolejnego ćwiczenia jest zobrazowanie sposobu wykorzystania wiązania zmiennych za pomocą JDBC. Utwórz serwlet JDBCPreparedQueryServlet. W metodzie init() załaduj właściwy sterownik. W metodzie doget() umieść metodzie poniższy kod String url = "jdbc:oracle:thin:@oracle-server.edu.wsnhid.pl:1521:orcl"; String username = "scott"; String password = "tiger"; response.setcontenttype("text/html"); response.setcharacterencoding("windows-1250"); PrintWriter out = response.getwriter(); Connection conn = DriverManager.getConnection(url, username, password); Statement stmt = conn.createstatement(resultset.type_forward_only, ResultSet.CONCUR_READ_ONLY); ResultSet rset = stmt.executequery("select id_zesp, nazwa FROM zespoly"); out.println("<html><head><title>preparedquery test</title></head>"); out.println("<table border=1><tr><th>zespoly</th></tr>"); while (rset.next()) { out.println("<td><a href=\"jdbcpreparedqueryservlet?id=" + rset.getint("id_zesp") + "\">" + rset.getstring("nazwa") + "</a></td></tr>"); out.println("</table>"); int id = 0; if (request.getparameter("id")!= null) { id = Integer.parseInt(request.getParameter("id")); PreparedStatement pstmt = conn.preparestatement("select * FROM zespoly WHERE id_zesp =?"); pstmt.setint(1, id); ResultSet zesp = pstmt.executequery(); zesp.next(); out.println("<h3>zespol</h3>"); out.println("<ul>"); out.println("<li>" + zesp.getint("id_zesp")); out.println("<li>" + zesp.getstring("nazwa")); out.println("<li>" + zesp.getstring("adres")); out.println("</ul>"); out.println("</body></html>"); out.close(); rset.close(); stmt.close(); conn.close(); catch (SQLException ex) { ex.printstacktrace();
11. Kolejne ćwiczenie pokazuje, w jaki sposób można modyfikować zawartość bazy danych wykorzystując mechanizm kursorów (zamiast poleceń SQL). Utwórz nowy serwlet JDBCUpdateServlet. W metodzie init() załaduj sterownik JDBC. W metodzie doget() umieść poniższy kod: response.setcontenttype("text/html"); response.setcharacterencoding("windows-1250"); String url = "jdbc:oracle:thin:@oracle-server.edu.wsnhid.pl:1521:orcl"; String username = "scott"; String password = "tiger"; String query = "SELECT id_prac, nazwisko, placa_pod FROM pracownicy"; Connection conn = DriverManager.getConnection(url, username, password); Statement stmt = conn.createstatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rset = stmt.executequery(query); conn.setautocommit(false); conn.settransactionisolation(connection.transaction_read_committed); int id = 0; if (request.getparameter("id")!= null) { id = Integer.parseInt(request.getParameter("id")); rset.first(); while (rset.getint("id_prac")!= id) rset.next(); float placa = rset.getfloat("placa_pod"); rset.updatefloat("placa_pod", placa + 101); rset.updaterow(); conn.commit(); PrintWriter out = response.getwriter(); response.setcontenttype("text/html"); response.setcharacterencoding("utf-8"); out.println("<html><head><title>updatequery test</title></head>"); out.println("<body><h2>pracownicy</h2>"); out.println("<table border=1><tr><th>nazwisko</th><th>płaca</th></tr>"); rset.first(); while (rset.next()) { out.println("<tr><td>" + rset.getstring("nazwisko") + "</td>"); out.println("<td>" + rset.getfloat("placa_pod") + "</td>"); out.println("<td><a href=\"jdbcupdateservlet?id=" + rset.getint("id_prac") + "\">podwyŝka</a></td></tr>"); out.println("</table>"); rset.close(); stmt.close(); conn.close(); catch (SQLException ex) { ex.printstacktrace(); catch (IOException ex) { ex.printstacktrace();
12. Ostatnie ćwiczenie pokazuje kroki konieczne do uruchomienia aplikacji w konfiguracji z pulą połączeń. Otwórz kod źródłowy serwletu JDBCTestServlet. Następnie, wykonaj następujące kroki: a) Dodaj specyfikację źródła danych do pliku $CATALINA_BASE/config/server.xml. Wewnątrz znacznika <GlobalNamingResources> umieść poniższy kod <Resource name="jdbc/oracle" auth="container" type="javax.sql.datasource" driverclassname="oracle.jdbc.oracledriver" url="jdbc:oracle:thin:@oracle-server.edu.wsnhid.pl:1521:dblab10g" username="xxx" password="xxx" maxactive="20" maxidle="10" maxwait="-1"/> b) Do katalogu $CATALINA_HOME/common/lib przekopiuj sterownik JDBC. Następnie, restartuj serwer aplikacji. c) Do deskryptora wdrożenia aplikacji web.xml dopisz deklarację wykorzystania zasobu. Bezpośrednio przed zamykającym znacznikiem </web-app> umieść poniższy kod <resource-ref> <res-ref-name>jdbc/oracle</res-ref-name> <res-type>javax.sql.datasource</res-type> <res-auth>container</res-auth> <res-sharing-scope>shareable</res-sharing-scope> </resource-ref> d) Do kodu źródłowego serwletu dodaj polecenia importujące pakiety javax.sql i javax.naming. Zastąp linie DriverManager.registerDriver( new oracle.jdbc.oracledriver() ); Connection conn = DriverManager.getConnection(url, username, password); liniami Context initcontext = new InitialContext(); DataSource ds = (DataSource)initContext.lookup("java:comp/env/jdbc/oracle"); Connection conn = ds.getconnection(); Pamiętaj, żeby obsłużyć wyjątek NamingException który może zostać zgłoszony podczas wyszukiwania źródła danych w JNDI.
Zadanie samodzielne Napisz serwlet, który wyświetli listę nazw zespołów. Każda nazwa jest odnośnikiem, którego kliknięcie powoduje wyświetlenie wietlenie listy nazwisk pracowników pracujących w danym zespole. Tabele mają schematy: ZESPOLY(id_zesp, nazwa, adres) PRACOWNICY(id_prac, nazwisko, etat, id_szefa, zatrudniony, placa_pod, placa_dod, id_zesp)