Delo s podatkovnimi bazami

Slides:



Advertisements
Similar presentations
1 Introduction to JDBC. 2 Road Map  Introduction to JDBC/JDBC Drivers  Overview: Six Steps to using JDBC  Example 1: Setting up Tables via JDBC  Example.
Advertisements

EE448: Server-Side Development Slide 1 EE448: Server-Side Development Lecturer: David Molloy Time: Tuesdays 3pm-5pm Notes:
1 JDBC: Java Database Connectivity. 2 Introduction to JDBC JDBC is used for accessing databases from Java applications Information is transferred from.
1 JDBC: Part I Attribution These slides are based on three primary sources: –Sun JDBC Tutorial URL: jdbc/TOC.htmlhttp://java.sun.com/docs/books/tutorial/
JDBC Overview Autumn 2001 Lecturer: C. DeJong. Relational Databases widespread use used via SQL (Structured Query Language) freely available powerful.
CS JDBC Introducing JDBC JDBC: is an API that provides “universal data access for the Java2 platform” Allows you to connect to a known data source.
Java Database Connectivity JDBC  JDBC is an API, containing classes and interfaces in the java programming language, to execute SQL sentences over an.
Three-Tier Architecture Oracle DB Server Apache Tomcat App Server Microsoft Internet Explorer HTML Tuples HTTP Requests JDBC Requests Java Server Pages.
1 JDBC "Java Database Connectivity". 2 Getting Started Guide: etstart/GettingStartedTOC.fm.html java.sql.
CS178 Database Management “JDBC”. What is JDBC ? JDBC stands for “Java DataBase Connectivity” The standard interface for communication between a Java.
June 1, 2000 Object Oriented Programming in Java (95-707) Java Language Basics 1 Lecture 8 Object Oriented Programming in Java Advanced Topics Java Database.
JDBC. What is JDBC JDBC is an acronym for –Java Data Base Connectivity. It allows java/jsp program to connect to any database.
Web Design & Development 1 Lec Web Design & Development 2 More on JDBC.
JDBC Tutorial MIE456 - Information Systems Infrastructure II Vinod Muthusamy November 4, 2004.
JDBC (Java Database Connectivity) SNU OOPSLA Lab. October 2005.
JDBC Java and Databases, including Postgress. JDBC l Developed by Industry leaders l Three main goals: –JDBC should be an SQL-level API –JDBC should capitalize.
Introduction to JDBC Michelle Lee, Ye Wu & Jeff Offutt SWE 432 Design and Implementation of Software for the Web.
JDBC. JDBC stands for Java Data Base Connectivity. JDBC is different from ODBC in that – JDBC is written in Java (hence is platform independent, object.
1 JDBC – Java Database Connectivity. 2 Introduction to JDBC JDBC is used for accessing databases from Java applications Information is transferred from.
COMP201 Java Programming Topic 15: Database Connectivity JDBC Reading: Chapter 4, Volume 2.
JDBC Database Programming in Java Prepared by., Mrs.S.Amudha AP/SWE.
JDBC. Java.sql.package The java.sql package contains various interfaces and classes used by the JDBC API. This collection of interfaces and classes enable.
JDBC CS 124. JDBC Java Database Connectivity Database Access Interface provides access to a relational database (by allowing SQL statements to be sent.
JDBC Part II CS 124. More about JDBC Types Statement versus PreparedStatement Timeout NULL values Meta-data close() methods Exceptions Transactions JDBC.
Basics of JDBC.
1 JDBC: Part II Road Map Using Prepared Statements –Statements v. Prepared Statements –Using Prepared Statements Database Joins Using Database Transactions.
JDBC (Java Database Connectivity)
Database Management Systems 1 Raghu Ramakrishnan Database Application Development Chpt 6 Xin Zhang.
JDBC Java DataBase Connectivity. Loading the driver import java.sql.*... Class.forName("org.postgresql.Driver")‏
Database Programming With Java & JDBC Reading: DD Ch. 18, pp al/jdbc/index.html, or anything covering JDBC.
1 JDBC: Java Database Connectivity. 2 Introduction to JDBC JDBC is used for accessing databases from Java applications Information is transferred from.
Intro to JDBC Joseph Sant Applied Computing and Engineering Sciences Sheridan ITAL.
CS422 Principles of Database Systems JDBC and Embedded SQL Chengyu Sun California State University, Los Angeles.
TIPI PODATKOV. Načrt Najprej je potrebno dobro premisliti o problemu Katere podatke hranimo, kako podatke razporediti v tabele, kakšne vrste podatkov.
JDBC Statements The JDBC Statement, CallableStatement, and PreparedStatement interfaces define the methods and properties that enables to send SQL or PL/SQL.
JDBC. What is JDBC JDBC is an acronym for –Java Data Base Connectivity. It allows java program to connect to any database.
JDBC Java Data Base Connectivity נערך ע"י: אורי רוטנברג הנחיה: ד"ר תמר בניה קורס: סדנא ב-Java.
1 JDBC – Java Database Connectivity THETOPPERSWAY.COM.
CS320 Web and Internet Programming Database Access with JDBC Chengyu Sun California State University, Los Angeles.
JDBC – Java DataBase Connectivity
CS JDBC.
CS3220 Web and Internet Programming Database Access with JDBC
EE557: Server-Side Development
Lec - 14.
JAVA Connection The following uses a ‘bridge’ between Java Database Connectivity (JDBC) and ODBC, namely sun.jdbc.odbc.JdbcOdbcDriver Supplied with the.
CS320 Web and Internet Programming Database Access with JDBC
HW#4 Making Simple BBS Using JDBC
Prof: Dr. Shu-Ching Chen TA: Sheng Guan
Design and Implementation of Software for the Web
JDBC – Java DataBase Connectivity
Uvod v Python
Delo s podatkovnimi bazami
R V P 2 Predavanje 04 Animacija RVP2 Animacija.
Grafični vmesnik - GUI Izdelava obrazca: lastnosti, odzivne metode
JDBC – Java DataBase Connectivity
JDBC 15-Nov-18.
Fotografiranje hrane Predmet: Tipografija in reprodukcija.
Tatjana Welzer Družovec (Inštitut za informatiko, FERI Maribor)
Kaj je Oddaljeno namizje (ON)?
Microsoftove rešitve za šolstvo
MS Excel, Open Office Calc, Gnumeric …
Ela Reven, Katarina urbančič
Ugani število Napišimo program, ki si “izmisli” naključno število, potem pa nas v zanki sprašuje, katero je izmišljeno število. Če število uganemo, nas.
E-mobilnost in njena integracija v elektroenergetski sistem
Bolat Azamat, Kim Dongmin
JDBC Example.
CS3220 Web and Internet Programming Database Access with JDBC
CS3220 Web and Internet Programming Database Access with JDBC
Java Database Connectivity JDBC
JDBC – Java DataBase Connectivity
Presentation transcript:

Delo s podatkovnimi bazami (JDBC)

Primer preproste podatkovne baze Nekaj pojasnil: Stranka (Customer) ima lahko več naročil (Orders). Posamezno naročilo (Order) ima lahko več zapisov OrderDetail. Vsak zapis OrderDetail se nanaša na natančno eno knjigo (Book). Vsi primarni ključi (polja ID) so avtomatsko generirani in jih zato pri vrivanju zapisov ne navajamo. OrderDetail.Quantity je tipa int. Books.BookPrice je tipa double . CustomerFirstName, CustomerLastName CustomerAddress in BookName are so tipa String. Orders.OrderDate je objekt tipa Date/Time

Interakcija s podatkovno bazo V tem poglavju pričakujemo poznavanje pojma podatkovne baze in povpraševalnega jezika SQL. Obravnavali bomo, kako lahko nek uporabniški program interaktira s podatkovno bazo. Programi so seveda pisani v različnih programskih jezikih in tečejo v različnih okoljih. Prav tako poznamo različne sisteme za upravljanje podatkovnih baz. Obravnavali bomo, kako lahko nek uporabniški program interaktira s podatkovno bazo. Programi so seveda pisani v različnih programskih jezikih in tečejo v različnih okoljih. Prav tako poznamo različne sisteme za upravljanje podatkovnih baz.

Standard ODBC Standard določa poenotene funkcijske klice, s katerimi se lahko pogovarjamo z različnimi podatkovnimi bazami.   Zamisel je v tem, da vsi uporabniški programi uporabljajo enake klice funkcij ne glede na to, s katero podatkovno bazo komunicirajo. Zato pa mora biti med njimi in podatkovno bazo še poseben modul, takoimenovani ODBC gonilnik (ODBC driver), ki te klice preslika v obliko, ki jo dani sistem za upravljanje s podatkovno bazo razume. Vsaka Vrsta SUPB torej zahteva svoj ODBC gonilnik. Microsoft je zato predlagal standard ODBC ( Open Data Base Connectivity), ki je namenjen komunikaciji uporabniških programov s podatkovnimi bazami.

Programi v Javi in JDBC JDBC (Java Database Connection) je standardna metoda za dostop do podatkovnih baz iz Jave. V bistvu je to aplikacijski programski vmesnik (API, Application Programming Interface). Sun je po zgledu Microsoftove tehnologije ODBC razvil knjižnico JDBC. Žal je ODBC kar kompleksen, ker nudi le nekaj, zato pa kompleksnih klicev. JDBC naj bi to kompleksnost poenostavil z uvedbo več bolj preprostih klicev Programi v Javi in dostop do podatkovnih baz s pomočjo JDBC

6 korakov za uporabo JDBC Naložimo JDBC Driver Vzpostavimo povezavo s podatkovno bazo (Database Connection) Tvorimo objekt Statement Izvedemo povpraševanje (Query) Obdelamo rezultat (Result) Zapremo povezavo (Connection)

Terminologija (pomen objektov) Connection Connection Statement Statement ResultSet ResultSet Program ima lahko eno ali več povezav (connections) do strežnikov podatkovnih baz Eni povezavi (connection) je lahko prirejen eden ali več stavkov (statement) Enemu stavku (statement) je lahko prirejenih eden ali več rezultatov (result).

Dostop do podatkovne baze preko JDBC Tvoriti moramo objekt Connection , ki je povezan s podatkovno bazo Tvorimo objekt Statement , s katerim odpremo objekt Connection  Povpraševalno izvajanje objekta Statement vrne  objekt ResultSet Sedaj lahko obdelamo vrstice v objektu  ResultSet Poleg te, običajne oblike imamo tudi njene različice. Namesto izjave Statement, tvorimo PreparedStatement (ki omogoča vnaprej pripravljena vprašanja in tako bolj učinkovito uporabo, na primer v zankah). Povpraševanje  update lahko vrne le število vrstic, ki so bile posodobljene, vrinjene ali zbrisane, ne vrne pa ResultSet. Na voljo imamo tudi klice, ki povedo podatke o objektih ResultSet  (na primer število, imena in tipe stolpcev). Na voljo so tudi klici za podporo transakcij s podatkovno bazo.

Paket java.sql Glavni paket, ki ga moramo uporabiti, je java.sql. Zato na začetku programa uporabimo stavek import java.sql.* ; Ta paket spada v standardno distribucijo JDK (Java Development Kit). Obstaja pa tudi njegova bolj napredna razširitev javax.sql, ki pa jo redko uporabljamo.

Gonilniki (drivers) Posamezni sistemi za upravljanje s podatkovnimi bazami zahtevajo za svoj dostop z vmesnikom JDBC ustrezen JDBC gonilnik. Sun ponuja kot del svoje standardne distribucije premostitveni gonilnik JDBC-ODBC. Ta nam omogoča povezavo s katerokoli podatkovno bazo, ki razume ODBC. Ker je ta gonilnik precej počasen, je primeren bolj za preskušanje in ni priporočljiv za poslovne aplikacije. Večina ponudnikov sistemov za upravljanje s podatkovnimi bazami nudi svoje gonilnike.

Nalaganje gonilnika Če želimo dostopiti do podatkovne baze, moramo najprej naložiti gonilnik. Seveda mora biti gonilnik nameščen na sistem (kar pomeni, da mora biti nameščena ustrezna »jar« datoteka z gonilnikom in navedena v poti (classpath)). Če uporabljamo premostitveni gonilnik JDBC-ODBC, moramo še našo podatkovno bazo registrirati z  ODBC Na sistemi MS Windows uporabimo orodje "ODBC data sources" v nadzornem panoju). Ime razreda gonilnika JDBC-ODBC je sun.jdbc.odbc.JdbcOdbcDriver. Ko je gonilnik naložen, se samodejno registrira s pomočjo orodja »Drivermanager« in je tako pripravljen za tvorbo objekta Connection. Obstaja več načinov nalaganja gonilnika. Omenimo le naslednjo: Razred System ima statični seznam lastnosti (Property). Če ta vsebuje lastnost jdbc.drivers nastavljeno na seznam  imenov razredov gonilnikov, ločen z dvopičji (":") , bodo ustrezni gonilniki samodejno naloženi in registrirani.  Ko zahtevamo povezavo, sistem izbere najbolj primeren gonilnik. Žal pa ta metoda ni primerna za delo s takoimenovanimi »servleti«. V tem primeru je bolje, da naložimo ustrezen razred dinamično.

Dinamično nalaganje gonilnika Dinamično nalaganje poteka med samim izvajanjem programa: Properties props = new Properties() ; FileInputStream in = new FileInputStream("Database.Properties") ; props.load(in) ;         String drivers = props.getProperty("jdbc.drivers") ; Class.forName(drivers) ;  Izgled datoteke Database.properties # Default JDBC driver and database specification jdbc.drivers      =  sun.jdbc.odbc.JdbcOdbcDriver database.Shop  =  jdbc:odbc:Shop

Tvorba povezave (Connection) Povezavo dobimo tako, da navedemo URL konkretne podatkovne baze, ki jo želimo uporabiti. Oblika tega URL je odvisna od uporabljenega gonilnika. URL podatkovne baze lahko dobimo potem, ko je gonilnik naložen in lahko uporabimo prej omenjeno datoteko z lastnostmi (properties). String database = props.getProperty("database.Shop") ; Connection con = DriverManager.getConnection(database) ; Opozorilo: Microsoft Access, do katerega dostopamo preko gonilnika  JDBC-ODBC, lahko tudi ne dopušča več sočasnih povezav (vsaj ne zanesljivo). To pomeni, da naša aplikacija ne sme imeti istočasno odprtih več objektov Connection. Zato je uporabnost Microsoft Access za spletno podatkovno bazo zelo omejena je pa še primerna za ozobraževalne namene). Če uporabimo premostitveni gonilnik JDBC-ODBC, je URL podatkovne baze  jdb:odbc:xxx , pri čemer je  xxx podatkovni vir ODBC, registriran za našo podatkovno bazo. (ime lastnosti, ki jo uporabimo, ni pomembno).

Uporaba objektov Statement Objekt Statement (izjava) dobimo iz povezave z naslednjim stavkom: Statement stmt = con.createStatement() ; Z objektom Statement lahko nato izvajamo ali nadziramo izvajanje različnih povpraševanj SQL. Uporabimo  stmt.executeUpdate z argumentom v obliki niza, ki vsebuje SQL stavek za posodobitev (INSERT, DELETE or UPDATE). Stavek vrne število posodobljenih vrstic. Uporabimo  stmt.executeQuery z argumentom v obliki niza, ki vsebuje SQL povpraševanje SELECT. Stavek vrne objekt  ResultSet, ki ga nato uporabimo za dostop do vrstic  rezultata povpraševanja. Uporabimo stmt.execute za izvajanje poljubnega SQL stavka kateregakoli tipa. Je pa pri tem stavku težje ugotavljanje rezultata, bodisi celega števila bodisi objekta ResultSet.  Ta stavek uporabimo, če želimo posplošen dostop do podatkovne baze oziroma za programirano tvorbo povpraševanj.

Uporaba objekta statement int count = stmt.executeUpdate("INSERT INTO Customers " +                                "(CustomerFirstName, CustomerLastName, CustomerAddress) "                                "VALUES ('Tony', 'Blair', '10 Downing Street, London')") ; ResultSet rs = stmt.executeQuery("SELECT * FROM Customers") ;// do something with count and RS Sintaksa stavkov SQL, ki jih posredujemo kot argument v obliki niza, se mora ujemati s sintakso, ki jo uporablja navezana podatkovna baza.  Primer: ResultSet rs = stmt.executeQuery("SELECT * FROM Customers" +                                  "WHERE CustomerLastName = 'O''Neill'") ;

Uporaba objektov ResultSet (1) Če ne poznamo točne strukture tabel (sheme) v ResultSet, jo lahko dobimo preko objekta ResultSetMetaData. ResultSetMetaData rsmd = rs.getMetaData() ; int colCount = rsmd.getColumnCount() ;  for (int i = 1 ; i <= colCount ; i++) {         if (i > 1) out.print(", ");         out.print(rsmd.getColumnLabel(i)) ; }out.println() ; Ko dobimo objekt ResultSet , lahko iz njega dobimo njegove vrstice oziroma polja v njegovih vrsticah: while (rs.next()) { for (int i = 1 ; i <= colCount ; i++) { if (i > 1) out.print(", "); out.print(rs.getObject(i)) ; } out.println() ;

Uporaba objektov ResultSet (2) Stolpce začnemo šteti od 1 dalje in ne  od 0, kot je sicer navada pri poljih v Javi. Lahko pa uporabimo metodo getObject na objektu ResultSet . Ta metoda sprejme kot argument ime stolpca. Na voljo imamo tudi metode  tipa  getxxx , v katerih namesto številke stolpca navedemo kot argument ime stolpca.  Zato lahko zgornjo kodo zapišemo tudi tako: while (rs.next()) { out.println( rs.getObject("CustomerID") + ", " + rs.getObject("CustomerFirstName") + ", " + rs.getObject("CustomerLastName") + ", " + rs.getObject("CustomerAddress") ) ; } Namesto metode getObject lahko uporabimo bolj specifične metode, kot na primer  getInt, getString, itd. Vendar ima njihova uporaba tudi pomanjkljivost. Če je tip polja primitiven, kot na primer  int, float itd., in če je v podatkovni bazi vrednost tega polja prazna, metoda ne zna vrniti nekaj, po čemer bi to ločili od normalne vrednosti. Če pa uporabimo metodo getObject in če je polje prazno, dobimo vrednost »null.

Objekti PreparedStatement Te objekte lahko uporabimo namesto objektov Statement. Objekti PreparedStatement imajo naslednje prednosti: Pri ponavljanih povpraševanjih (na primer v zankah) je to bolj učinkovito, ker so stavki SQL prevedeni le enkrat Mehanizem vključevanja vrednosti parametrov poskrbi za vse posebne znake PreparedStatement pstmt = con.prepareStatement( "INSERT INTO Customers " + "(CustomerFirstName, CustomerLastName, CustomerAddress) "+ "VALUES (?, ?, ?)") ; pstmt.clearParameters() ; pstmt.setString(1, "Joan") ; pstmt.setString(2, "D'Arc") ; pstmt.setString(3, "Tower of London") ; count = pstmt.executeUpdate() ; System.out.println ("\nInserted " + count + " record successfully\n") ; pstmt.setString(1, "John") ; pstmt.setString(2, "D'Orc") ; pstmt.setString(3, "Houses of Parliament, London") ; Objekt  PreparedStatement vzpostavi tekst SQL, koga tvorimo. Parametre navedemo z znaki  '?' . Po tvorbi lahko te parametre počistimo z metodo clearParameters  in nastavimo z metodami  setInt, setString, itd.  (pozicije parametra začnemjo z 1) . Objekt nato izvedemo z metodami  execute, executeUpdate ali executeQuery kot pri objektu Statement , povrnjene pa dobimo enake tipe, vendar brez argumentov (saj smo stavke SQL že nastavili pri tvorbi objekta):

Transakcije Transakcije so mehanizem za skupinske operacije v tem smislu, da uspejo vse ali pa nobena. To prepreči nekonsistenčne probleme v podatkovni bazi, ki bi nastali, če bi se uspešno izvedel le del operacij. Pomislimo na primer, da bi želeli prestaviti del denarja iz enega računa na drugi in da bi dvig denarja uspel, polog na drugi račun pa ne. Žalostno, kaj ne?  Če to izvedemo kot transakcijo, je prva operacija (dvig) veljavna le, če tudi drugi del (polog) uspe.

Transakcije in JDBC Ko smo dobili povezavo »Connection« je lastnost AutoCommit nastavljena na  true. To pomeni, da je vsaka izvedba povpraševanja zapomnjena takoj po svoji izvedbi in preden začnemo izvajati naslednje povpraševanje. Če želimo združevati operacije v transakcije, moramo lastnost AutoCommit izključiti: con.setAutoCommit(false) ; Sedaj moramo dobiti nov objekt Statement (stari ne bo več deloval) in ga uporabljamo na že znani način. Ko zaključimo v se želene operacije, zahtevamo, njihovo pomnenje z naslednjim ukazom: Če pride do izpada podatkovne baze ali celo računalnika se bo v bistvu operacija »rollBack« izvedla samodejno pri ponovnem zagonu podatkovne baze. Čas izvajanja posameznih transakcij moramo minimizirati, saj transakcije zadržujejo veliko virov in v bistvu zaklepajo podatkovno bazo. In tako onemogočajo druge transakcije. Pri deli s transakcijami moramo biti previdni in rokovati s takoimenovanimi izjemami (exception handling). .Zato moramo transakcije vgraditi v oddelek try, ki ga v javanskih programih dobro poznamo. V primeru neuspešne transakcije izvedemo klic rollback.   con.commit() ; Če pride med izvajanjem transakcije do težav (recimo, da nismo mogli izvesti vseh operacij transakcije), lahko vse dotedanje operacije razveljavimo z ukazom: con.rollBack() ;

Popoln primer: podatkovna baza o kavici Vzpostavitev tabele (preko JDBC) Vključevanje zapisov (preko JDBC) Poizvedovanje (preko JDBC)

Vzpostavitev tabele (1) import java.sql.*; public class CreateCoffees { public static void main(String args[]) { String url = "jdbc:mysql://localhost/cerami"; Connection con; String createString; createString = "create table COFFEES " + "(COF_NAME VARCHAR(32), " + "SUP_ID INTEGER, " + "PRICE FLOAT, " + "SALES INTEGER, " + "TOTAL INTEGER)"; Statement stmt;

Vzpostavitev tabele (2) try { Class.forName("com.mysql.jdbc.Driver"); } catch(java.lang.ClassNotFoundException e) { System.err.print("ClassNotFoundException: "); System.err.println(e.getMessage()); } con = DriverManager.getConnection(url); stmt = con.createStatement(); stmt.executeUpdate(createString); stmt.close(); con.close(); } catch(SQLException ex) { System.err.println("SQLException: " + ex.getMessage());

Vključevanje zapisov (1) import java.sql.*; public class InsertCoffees { public static void main(String args[]) throws SQLException { System.out.println ("Adding Coffee Data"); ResultSet rs = null; PreparedStatement ps = null; String url = "jdbc:mysql://localhost/cerami"; Connection con; Statement stmt; try { Class.forName("org.gjt.mm.mysql.Driver"); } catch(java.lang.ClassNotFoundException e) { System.err.print("ClassNotFoundException: "); System.err.println(e.getMessage()); }

Vključevanje zapisov (2) try { con = DriverManager.getConnection(url); stmt = con.createStatement(); stmt.executeUpdate ("INSERT INTO COFFEES " + "VALUES('Amaretto', 49, 9.99, 0, 0)"); "VALUES('Hazelnut', 49, 9.99, 0, 0)"); "VALUES('Amaretto_decaf', 49, 10.99, 0, 0)"); "VALUES('Hazelnut_decaf', 49, 10.99, 0, 0)"); stmt.close(); con.close(); System.out.println ("Done"); } catch(SQLException ex) { System.err.println("-----SQLException-----"); System.err.println("SQLState: " + ex.getSQLState()); System.err.println("Message: " + ex.getMessage()); System.err.println("Vendor: " + ex.getErrorCode()); } }}

Poizvedovanje (1) import java.sql.*; public class SelectCoffees { public static void main(String args[]) throws SQLException { ResultSet rs = null; PreparedStatement ps = null; String url = "jdbc:mysql://localhost/cerami"; Connection con; Statement stmt; try { Class.forName("org.gjt.mm.mysql.Driver"); } catch(java.lang.ClassNotFoundException e) { System.err.print("ClassNotFoundException: "); System.err.println(e.getMessage()); } con = DriverManager.getConnection(url); stmt = con.createStatement();

Poizvedovanje (2) ResultSet uprs = stmt.executeQuery("SELECT * FROM COFFEES"); System.out.println("Table COFFEES:"); while (uprs.next()) { String name = uprs.getString("COF_NAME"); int id = uprs.getInt("SUP_ID"); float price = uprs.getFloat("PRICE"); int sales = uprs.getInt("SALES"); int total = uprs.getInt("TOTAL"); System.out.print(name + " " + id + " " + price); System.out.println(" " + sales + " " + total); } uprs.close(); stmt.close(); con.close(); } catch(SQLException ex) { System.err.println("-----SQLException-----"); System.err.println("SQLState: " + ex.getSQLState()); System.err.println("Message: " + ex.getMessage()); System.err.println("Vendor: " + ex.getErrorCode()); } }}