Sunteți pe pagina 1din 50

153

Realizarea rapoartelor

Rapoartele prezintă într-un format impus date conŃinute în baza de date. În


unele cazuri formatul în care datele trebuie prezentate datele este definit prin lege.
AplicaŃiile care accesează servere de baze de date trebuie să asigure afişarea
pe ecran a rapoartelor şi imprimarea lor.
Un raport conŃine de regulă nouă regiuni dispuse în benzi, ca în figură.
LăŃimile benzilor sunt astfel stabilite încât să ocupe întreaga zonă utilă (imprimabilă)
a paginii.

Titlul (Title)

Cap pagină (Page Header)

Cap coloană (Column Header)

Detaliere (Detail)

Picior coloană (Column Footer)

Picior pagină (Page Footer)

Recapitulare (Summary)

Titlul
Banda pentru titlu este prima dintr-un raport. Un raport conŃine numai o
singură bandă pentru titlu. Aceasta poate fi dispusă pe o pagină separată.

Capul paginii
Banda pentru capul paginii apare la începutul fiecărei pagini a raportului.
Dacă titlul raportului sau recapitularea apar pe pagini separate, acestea nu vor
conŃine această regiune.

Capul coloanei
InformaŃiile dintr-un raport pot fi dispuse pe una sau mai multe coloane.
154

Raport pe o coloană Raport pe două coloane

Column header Column header Column header

  


     
     
     
     

  


     
     
     
     

Raport pe o coloană
(date dispuse tabelar)
Column header
    
   
1.
   
2.
   
3.
   
4.

Detaliere
În cazul rapoartelor în care informaŃia nu este grupată, în această regiune
sunt afişate rânduri conŃinând date preluate din baza de date.
În cazul rapoartelor în care informaŃia apare organizată în grupuri, în această
regiune vor alterna benzi conŃinând antetul grupului (Group Header) respectiv datele
conŃinute în grup. După fiecare grup este posibilă afişarea unei benzi (Group Footer)
conŃinând un rezumat legat de datele conŃinute în grupul respectiv.

Picior coloană
Banda care încheie coloana poate conŃine informaŃii recapitulative, de regulă
sume sau numărul de articole conŃinute în regiunea de detaliere.

Picior pagină
Toate paginile care conŃin o bandă destinată capului paginii pot conŃine în
partea de jos o bandă pentru informaŃii recapitulative la nivel de pagină. Este posibilă
includerea unei benzi distincte pentru ultima pagină a raportului (Last Page Footer).
155

Recapitulare
Banda pentru recapitulare (Summary) este adăugată la sfârşitul raportului,
eventual pe o pagină distinctă.

Fundal
Fundalul raportului (Background) poate fi impus. De regulă acesta constă
dintr-o imagine care va fi repetată pe toate paginile raportului.

Jasper Reports
Realizarea comodă a rapoartelor se poate face folosind o aplicaŃie specializată.
Există o multitudine de astfel de aplicaŃii, mai interesantă fiind Jasper Reports, o
soluŃie gratuită (open source) propusă de JasperSoft Corporation (fondată de românul
Teodor Danciu).
Jasper Reports constă dintr-o colecŃie de clase Java care pot fi adăugate
aplicaŃiilor scrise în acest limbaj. Jasper Reports oferă de altfel o mulŃime de funŃii.
Astfel, pe lângă vizualizarea şi imprimarea imediată a raportului, datele acestuia pot fi
exportate într-o multitudine de formate: HTML, XML, XLS (Microsoft Excel), RTF
(Microsoft Word), PDF sau reprezentate grafic.
Principial un ciclu de lucru pentru crearea unui raport folosind Jasper Reports
constă din paşii următori:
1. Se crează un fişier de descriere a raportului în format XML, având extensia
.jrxml;
2. Fişierul .jrxml este compilat pentru a-l aduce într-o formă accesibilă
claselor Jasper Reports;
3. Se realizează interogarea sursei de date pentru aducerea datelor care vor fi
conŃinute în raport;
4. Se vizualizează şi se imprimă raportul.
Deoarece fişierul de descriere a raportului în format XML este relativ dificil de
creat, mai ales pentru rapoarte având o grafică îngrijită şi o structură nu tocmai
banală, în practică se foloseşte o aplicaŃie independentă, iReport. Autorul acesteia
este Giulio Toffoli (Italia, 2002). Sesizând interesului cu care a fost primită soluŃia
Jasper Reports de programatorii în Java, acesta a creat un mediu vizual destinat
realizării rapoartelor, bazat pe JasperReports. Acesta permite crearea interactivă a
raportului dorit şi salvarea fişierului în format .jrxml conŃinând descrierea acestuia.

Realizarea descrierii raportului cu iReport


iReports este un mediu vizual de editare a rapoartelor. Fereastra aplicaŃiei
cuprinde mai multe panouri cu instrumente.
156

După descărcarea şi instalarea aplicaŃiei iReport (http://ireport.sf.net/)


aceasta trebuie configurată în vederea conectării la serverul Oracle XE. În principiu
configurarea presupune două acŃiuni:
- indicarea căii spre directorul conŃinând driverul jdbc necesar conectării şi
- realizarea unei conexiuni cu serverul.

Indicarea căii spre biblioteca ojdbc14_g.jar


Ca şi în cazul realizării unei aplicaŃii Java care accesează serverul Oracle XE, şi
în iReports va fi indicată calea spre biblioteca ojdbc14_g.jar conŃinând driverul jdbc şi
clasele necesare accesării serverului. Pentru aceasta se selectează Options /
Classpath:
157

După revenirea în fereastra Classpath se selectează Save Classpath:


158

Realizarea unei conexiuni cu serverul Oracle XE

În continuare se va realiza o conexiune cu serverul Oracle XE. Pentru aceasta


se va selecta în meniul aplicaŃiei Data / Connections/Data Sources:
159

Odată cu testarea conexiunii configurarea aplicaŃiei iReport în vederea


realizării de rapoarte bazate pe tabelele şi vederile din baza biblio este încheiată.

Realizarea unei conexiuni cu serverul MySQL

Datorită răspândirii sale, cunoaşterea modului de conectare la acest server din


aplicaŃiile care operează cu baze de date poate fi deosebit de utilă.
160

Pentru a putea realiza o conexiune cu serverul MySQL dintr-o aplicaŃie Java,


trebuie descărcată de la adresa:
http://dev.mysql.com/downloads/connector/j/5.1.html
Connector/J 5.1 (sau o versiune ulterioară). Aceasta conŃine printre altele driverul
JDBC care trebuie utilizat. Fişierul descărcat poartă numele mysql-connector-java-
5.1.5.zip. Arhiva .zip conŃine printre altele mysql-connector-java-5.1.5-bin.jar care
trebuie adăugat aplicaŃiilor Java care accesează serverul.

Constructorul clasei principale a aplicaŃiei (denumită în exemplul analizat


ConectMySQL) trebuie să realizeze încărcarea driverului jdbc şi apoi să creeze
conexiunea cu serverul (un obiect din clasa Connection) care va fi folosită în
contiunare pentru crearea obiectelor Statement, ca şi în cazul aplicaŃiilor deja
realizate.
public ConectMySQL() {
initComponents();
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
System.exit(1);
}
try {
cnx = DriverManager.getConnection("jdbc:mysql://localhost/postuniv", "root", "");
poza.setIcon(new javax.swing.ImageIcon("./Poze/conect.jpg"));
} catch (SQLException ex) {
161

ex.printStackTrace();
poza.setIcon(new javax.swing.ImageIcon("./Poze/disconect.jpg"));
}
}

Pentru testarea conexiunii va fi pornit în prealabil serverul MySQL.

Pentru pregătirea realizării de rapoarte cu iReports se procedează astfel:


1. Se indică aplicaŃiei iReports calea spre arhiva mysql-connector-java-5.1.5-bin.jar:
162

2. Cu serverul MySQL pornit, se selectează Data / Connections/Data Sources:


163

După testare se salvează conexiunea şi se poate începe realizarea rapoartelor dorite.

Exemplul 1
Să se creeze un raport care să afişeze editurile de la care provin cărŃile din
bibliotecă.

Report wizard construieşte un raport în cinci paşi.


Pasul1: Se defineşte interogarea care furnizează datele conŃinute în raport.
Pentru aceasta, în prima fereastră care se afişează se introduce interogarea sau se
apasă butonul Design query pentru a genera fraza SQL folosind un generator
specializat.
164

Pentru raportul considerat comanda SELECT este:


select * from edituri

Pasul 2: Se selectează câmpurile care vor fi conŃinute în raport:


165

Pasul 3: În acest pas se poate indica gruparea înregistrărilor. În cazul ales nu


este necesară gruparea.
Pasul 4: În acest pas se impune aspectuil raportului (pe coloane sau tabelar,
respectiv modelul şi dispunerea în pagină).

Pasul 5: În acest ultim pas iReport confirmă realizarea raportului. După


afişarea butonului Finish se obŃine practic descrierea raportului.
166

Pentru vizualizarea raportului generat se selectează în meniul aplicaŃiei Build /


Execute (with active connection) sau se apasă butonul corespunzător de pe bara cu
instrumente:

În continuare se pot edita elementele conŃinute în diferitele regiuni ale


raportului. Pentru a edita un element conŃinut în raport se va selecta elementul şi
apoi se vor accesa şi eventual modifica proprietăŃile acestuia.
Obiectele conŃinute în raport pot fi editate selectându-le cu butonul drept al
mouse-ului în fereastra aplicaŃiei sau în fereastra Document structure şi accesând
opŃiunea Properties:
167

Tot folosind mouse-ul se pot modifica lăŃimile zonelor raportului sau se pot
deplasa (rearanja) obiectele în cadrul zonelor sau pot fi deplasate dintr-o regiune
într-alta.

Câmpuri, Parametri, variabile


O casetă dintr-un raport poate conŃine:
• un şir simplu de caractere,
• un câmp dintr-un tabel sau dintr-o vedere,
• o variabilă,
• un parametru sau,
• expresie.
Câmpurile (fields) sunt incluse prin intermediul frazei SELECT care stă la baza
realizării raportului. Clasa Java care le este asociată implicit depinde de natura
informaŃiei din coloana tabelului sau vederii din care provin. Clasele posibile sunt
următoarele:

Cele mai folosite sunt java.lang.String (asociată tipurilor SQL CHAR sau
VARCHAR2), java.math.BigDecimal (asociată implicit tipului SQL NUMBER) şi
java.util.Date (asociat tipului SQL DATE). Pentru referirea la câmpuri se foloseşte
sintaxa:
$F{nume_camp}
Variabilele servesc la producerea unor valori care variază de la o linie la alta
(un contor de linii de exemplu) sau a unor valori calculate pe baza valorilor
câmpurilor (sume, medii, valori extreme etc.). AplicaŃia iReports defineşte implicit un
număr de variabile.

Pentru a referi o variabilă se foloseşte sintaxa:


$V{nume_var}

Parametrii sunt obiecte având valori fixe, definite în momentul declarării lor.
AplicaŃia care va genera efectiv raportul va înlocui însă valorile implicite ale acestora
168

cu valorile lor efective (înaintea populării cu date a raportului prin interogarea bazei
de date).
Pentru a referi un parametru se foloseşte sintaxa:
$P{nume_parametru}

Expresiile care definesc conŃinutul unei casete trebuie să producă un obiect


Java. Clasa acestui obiect şi clasa casetei (implicită sau impusă accesându-i
proprietăŃile) trebuie să coincidă.
Expresiile pot conŃine referiri la câmpuri, parametri sau variabile.
Exemple:
• "Debitori"
• $F{JUDET}
• "-" + "Pagina " + $V{PAGE_NUMBER} + " - "
• new Boolean(true)
• new Integer(3)
• (($P{parametru}.equals(“RON”)) ? “RON” : “EUR”)
• new Double($F{f1}.doubleValue() + $F{f2}.doubleValue())
• $F{nume}.trim() + " " + $F{initiala} + ". " + $F{prenume}.trim() +
(($F{nume_nou}.trim().length() > 0) ? " (cas. " + $F{nume_nou} +
")" : "")
169

ObservaŃie: Frecvent formatul valorilor afişate este diferit de cel natural.


Astfel într-o primă formă data calendaristică şi rezultatul unui calcul ar putea fi afişate
ca în figură:

Pentru impunerea formatului dorit se accesează proprietatea Pattern.

- pentru data calendaristică:

pentru valoarea numerică în dublă precizie:


170

Rezultat posibil:

Crearea frazei SELECT


În pasul 1 al procesului de realizare al raportului folosind Report wizard se
poate selecta butonul Design query. Ulterior, dacă se doreşte modificarea frazei
SELECT se va selecta Data / Report Query iar în fereastra afişată se va selecta Query
designer:
171

În fereastra de construire a interogării se vor selecta cu dublu clic tabelele şi


vederile pe care se bazează raportul. Pentru fiecare tabel se vor selecta câmpurile
care trebuie să fie conŃinute în raport.
Dacă între tabelele selectate există legături persistente, acestea vor fi
evidenŃiate de aplicaŃie.
172

Modul de operare a unei legături (inner join, left/right outer join) poate fi
impus selectând cu un dublu clic marcajul de pe arcul care indică legătura.
Adăugarea condiŃiilor suplimentare incluse în clauza where se realizează
selectând în arborele din panoul drept WHERE/add condition.

În cazul dat condiŃia face referire la parametrul judeŃ. Parametrul trebuie


evident adăugat folosind fereastra Document structure.
173

Adăugarea unui contor pentru linii

Dacă liniile raportului trebuie să fie numerotate, o soluŃie este inserarea unei
variabile ale cărei valori vor fi afişate în prima coloană a raportului.
Pentru inserarea unei variabile se va selecta cu butonul drept al mouse-ului
intrarea Variables din fereastra Document structure şi apoi se va alege în meniul
contextual Add... / Variable.

Numele variabilei va fi nr_crt, restul proprietăŃilor fiind impuse ca în figură.


Pentru Calculation Type se va selecta Count. AplicaŃia permite şi alte tipuri de
calcule, interesant fiind tipul Sum.
174

Pentru inserarea valorilor variabilei în raport se va insera în regiunea Detail o


casetă de text deplasând în prealabil casetele existente (în Detail şi în Column
header) spre dreapta.

ProprietăŃile casetei vor fi modificate astfel încât textul afişat să aibă aceleaşi
caracteristici cu cel afişat de celelalte casete de text. Pentru a impune conŃinutul
casetei se va selecta tabul Text field valorile fiind setate ca în figură.
175

Rezultat posibil:

În această etapă raportul poate fi salvat (File / Save, rezultatul fiind un fişier
în format .jrxml).

Integrarea raportului în aplicaŃie

Pentri a integra raportul într-o aplicaŃie scrisă în Java este necesar să se


parcurgă paşii următori:
1. Se crează în directorul aplicaŃiei un subdirector denumit Rapoarte şi se
copiază în acest subdirector fişierul edituri.jrxml creat de iReport;
2. Se adaugă într-unul dintre meniurile derulante al aplicaŃiei o nouă intrare.
Selectarea noii opŃiuni va declanşa realizarea raportului şi afişarea sa într-o
fereastră similară cu cea folosită la vizualizare în iReport.
3. Se adaugă aplicaŃiei un ansamblu de arhive .jar: commons-beanutils-
1.7.jar, commons-collections-2.1.jar, commons-digester-1.7.jar, commons-
logging-1.0.2.jar, jasperreports-2.0.1.jar, jdt-compiler-3.1.1.jar. Acestea
sunt folosite şi de iReport şi se găsesc în directorul Program Files /
JasperSoft/iReport-2.0.1/lib.
ObservaŃie: JasperReports şi iReport fiind produse cu o dezvoltare rapidă şi
continuă, versiunile fişierelor menŃionate pot diferi.
176

Metoda executată la selectarea opŃiunii din meniu adăugată pentru realizarea


raportului va conŃine declararea variabilei raport care conŃine calea spre fişierul .jrxml
generat de iReport şi trei linii de cod realizând o compilare a fişierului .jrxml (metoda
compileReport), interogarea bazei de date pentru aducerea datelor în raport (metoda
fillReport) şi vizualizarea raportului într-o fereastră similară celei folosite de iReport
(metoda viewReport).

private void ButonRaportActionPerformed(java.awt.event.ActionEvent evt) {


// TODO add your handling code here:
String raport = "./Rapoarte/edituri.jrxml"; // Fisier realizat de iReports
HashMap params = new HashMap();
// se definesc valorile celor 2 parametri din raport, editura si an_ref

params.put("editura", edit); // edit e String si e preluat din formular (comboEdituri)


int anul = Integer.parseInt(anreferinta.getString());
params.put("an_ref", anul); // anul de referinta
// Se poate face raportul
try {
JasperReport jasperReport = JasperCompileManager.compileReport(raport);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, params, cnx);
JasperViewer.viewReport(jasperPrint, false);
}
catch (JRException ex) {
ex.printStackTrace();
}
}

Presupunând că raportul care trebuie realizat afişează cărŃile unei edituri


apărute după un an precizat, în iReports la construirea raportului s-au definit doi
parametri, editura şi an_ref. În secvenŃa de cod prezentată, înaintea generării
177

raportului se impun valorile efective ale celor doi parametri. Acestea provin din două
controale ale formularului realizat în acest scop. SecvenŃa de cod prezentată este
executată la apăsarea butonului ButonRaport de pe acelaşi formular.
Pentru afişarea şi imprimarea altor rapoarte ale aplicaŃiei funŃiile necesare vor
fi similare celei scrise, singura diferenŃă fiind numele fişierului .jrxml şi secvenŃa de
preluare a valorilor eventualilor parametri.

Realizarea rapoartelor conŃinând grupuri de articole


Rapoartele pot fi cu mult mai complexe decât cel realizat. Un exemplu în
acest sens este raportul prezentat în continuare în care se doreşte afişarea cărŃilor
unei biblioteci grupate pe edituri.
Pentru crearea unei prime forme a raportului se va face apel la iReport
wizard:

Fraza SELECT pe care se va baza raportul este următoarea:

SELECT
CARTI."TITLU" AS CARTI_TITLU,
CARTI."AN_APAR" AS CARTI_AN_APAR,
EDITURI."NUME" AS EDITURI_NUME,
EDITURI."TELEFON" AS EDITURI_TELEFON
FROM
"BIBLIO"."EDITURI" EDITURI INNER JOIN "BIBLIO"."CARTI" CARTI ON
EDITURI."COD_EDIT" = CARTI."COD_EDIT"
ORDER BY EDITURI.NUME ASC, CARTI.TITLU ASC
178
179

AplicaŃia va adăuga raportului două benzi pentru REGIUNI_NUME. În zona


REGIUNI_NUME de deasupra benzii DETAIL vor fi introduse datele editurilor.
Rezultat posibil, după editarea şi rearanjarea elementelor raportului.
180

Pregătirea aplicaŃiei pentru distribuŃie

În urma testării, aplicaŃia trebuie pregătită astfel încât să poată fi lansată în execuŃie
şi fără utilizarea mediului de programare Netbeans. Pentru a realiza aceasta se va
selecta opŃiunea Build / Build Main Project. Mediul de programare va adăuga directorului
aplicaŃiei un subdirector denumit dist care va coŃine o arhivă .jar executabilă. Pe lângă
aceasta directorul dist va mai conŃine subdirectorul lib. În acest subdirector mediul
Netbeans va copia toate bibliotecile adăugate proiectului în timpul realizării sale (în
Libraries).

Dacă aplicaŃia mai conŃine fişiere şi în alte directoare, şi este de regulă cazul
fişierelor .jrxml care conŃin descrierea rapoartelor, în dist vor trebui copiate şi aceste
directoare. În exemplul ales s-au copiat două subdirectoare, Rapoarte şi Poze.
Lansarea în execuŃie fără Netbeans se realizează selectând arhiva executabilă cu
butomul drept al mouse-ului şi apoi Open With / Java Platform SE binary.
181

Laborator nr. 11

InterfaŃa aplicaŃiei. Formulare complexe.

6. PorniŃi aplicaŃia NetBeans.


7. AdăugaŃi proiectului biblio o altă intrare în submeniul Adaugare, Carti – de tip JMenuItem:

8. CreaŃi un formular pentru introducerea cărŃilor în baza de date, astfel:

4. AdăugaŃi intrării acarti ( = adaugare cărŃi) evenimentului actionPerformed codul:


ACarti.setLocation(120,170);
ACarti.setVisible(true);
ACarti.pack();

5. Pentru funcŃionarea corectă a formularului:

• declaraŃi patru variabile globale , două de tip Statement şi două de tip ResultSet:
182

Statement autorii ;
ResultSet rezultat_autorii ;

Statement editurile ;
ResultSet rezultat_editurile ;

• la deschiderea formularului trebuie să se execute o secvenŃă de cod pentru popularea


celor două controale de tip JComboBox, unul pentru lista autorilor şi celălalt pentru lista
editurilor din baza de date:

private void ACartiWindowActivated(java.awt.event.WindowEvent evt) {


// TODO add your handling code here:
try {
//populez lista autorilor
autorii = cnx.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
rezultat_autorii = autorii.executeQuery("SELECT * from autori order by nume");

autor.removeAllItems();
while (rezultat_autorii.next()) {
String n = rezultat_autorii.getString("nume")+rezultat_autorii.getString("prenume");
autor.addItem(n);
}

//populez lista editurilor


editurile = cnx.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
rezultat_editurile = editurile.executeQuery("SELECT * from edituri order by nume");

editura.removeAllItems();
while (rezultat_editurile.next()) {
String n = rezultat_editurile.getString("nume");
editura.addItem(n);
}

} catch (SQLException ex) {


ex.printStackTrace();
}

• la închiderea formularului trebuie distruse cele două obiecte din clasa Statement:
private void CartiAutWindowDeactivated(java.awt.event.WindowEvent evt) {
// TODO add your handling code here:
try {
autorii.close();
editurile.close();
183

} catch (SQLException ex) {


ex.printStackTrace();
}

• adăugaŃi clasei principale două variabile, codaut şi codedit pentru preluarea codurilor
autorului şi editurii selectate;
• la modificarea elementului selectat din controlul de tip JComboBox autor preluaŃi codul
autorului selectat de utilizator, astfel:
try {
// Se selecteaza codul autorului
int linie = autor.getSelectedIndex();
if (linie>=0){
rezultat_autorii.absolute(linie+1);
codaut = rezultat_autorii.getInt("Cod_aut");
}
} catch (SQLException ex) {
ex.printStackTrace();
}

• la modificarea elementului selectat din controlul de tip JComboBox editura preluaŃi


codul editurii selectate de utilizator, astfel:
try {
// Se selecteaza codul editurii
int linie = editura.getSelectedIndex();
if (linie>=0){
rezultat_editurile.absolute(linie+1);
codedit = rezultat_editurile.getInt("cod_edit");
}
} catch (SQLException ex) {
ex.printStackTrace();
}

• adăugaŃi secvenŃa de cod executată la apăsarea butonului "Iesire":


ACarti.setVisible(false);

• editaŃi metoda asociată butonului "Adaugare":


try {
String tit, an;

tit = titlu.getText();
184

an = anul.getText();

String frazaSQL = "INSERT into carti VALUES (autocarte.NEXTVAL";


frazaSQL += "," + apostrof(tit)+ "," + codedit + "," + apostrof(an) + ")";

// Creez un Statement*/
Statement stm = cnx.createStatement();

// Apelez metoda executeUpdate() pt. a trimite comanda INSERT


System.out.println(frazaSQL);
stm.executeUpdate(frazaSQL);

//preiau codul cartii introduse


int c;
Statement s = cnx.createStatement();
ResultSet r = s.executeQuery("SELECT autocarte.CURRVAL as c from
dual");
r.next();
c = r.getInt("c");

//adaug cartea si in autcarti


String fraza1SQL = "INSERT into autcarti VALUES (" +codaut + "," + c + ")";

System.out.println(fraza1SQL);
stm.executeUpdate(fraza1SQL);
stm.close();

//golesc campurile
titlu.setText("");
anul.setText("");

} catch (SQLException ex) {


ex.printStackTrace();
}

6. CreaŃi un formular pentru efectuarea unui împrumut, astfel::


185

• adăugaŃi clasei principale patru variabile, două de tip Statement şi două de tip ResultSet:
Statement cititorii ;
ResultSet rezultat_cititorii ;

Statement cartile ;
ResultSet rezultat_cartile ;

• la deschiderea formularului trebuie rulat codul pentru popularea celor două controale de
tip JComboBox, unul pentru lista codurilor cititorilor şi celălalt pentru lista cartilor din
baza de date şi pentru popularea textboxului cu data curentă (data sistemului):

try {
//populez lista cu codurile cititorilor
cititorii = cnx.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
rezultat_cititorii = cititorii.executeQuery("SELECT * from cititori order by cod_cit");

cod_cititor.removeAllItems();
while (rezultat_cititorii.next()) {
String n = rezultat_cititorii.getString("cod_cit");
cod_cititor.addItem(n);
}

//populez lista cu cartile


cartile = cnx.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
rezultat_cartile = cartile.executeQuery("SELECT * from carti order by titlu");

cartea.removeAllItems();
while (rezultat_cartile.next()) {
String n = rezultat_cartile.getString("titlu");
cartea.addItem(n);
}

// scriu data de azi in textbox


Calendar azi = Calendar.getInstance();
SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy");
dataimpr.setText(fmt.format(azi.getTime()));

} catch (SQLException ex) {


ex.printStackTrace();
}

• la închiderea formularului se rulează


186

try {
cititorii.close();
cartile.close();
} catch (SQLException ex) {
ex.printStackTrace();
}

ObservaŃie: după selectarea codului cititorului (scanarea de ex. cu cititorul de coduri de bare
de pe legitimaŃia de bibliotecă), se fac mai multe lucurui simultan:
a. se afişează datele de identificare ale acestuia în cele două controlae de tip JTextField;
b. se populeaza controlul de tip JTable cu cărŃile împrumutate de respectivul cititor
c. adăugaŃi clasei principale variabila codcit pentru preluarea codului cititorului selectat;
d. adăugaŃi aplicaŃiei o nouă clasă, TbModel_3 derivată din AbstractTableModel.

public class TbModel_3 extends AbstractTableModel{


private String[] colNume={"Cartea","Data imprumutului","Data restituirii"};
private ArrayList dateContinute; // va fi ArrayList de ArrayList

/** Creates a new instance of TbModel */


public TbModel_3(ResultSet rs) {
dateContinute = new ArrayList();

try{
while(rs.next()){
ArrayList linie = new ArrayList();
String cartea = rs.getString("titlu");
Date datai = rs.getDate("data_imprumut");
Date datar = rs.getDate("data_rest");
linie.add(cartea);
linie.add(datai);
linie.add(datar);
dateContinute.add(linie);
}
} catch(Exception e){
System.out.println("Exceptie in TbModel");
}

public Object getValueAt(int linie, int col) {


// Preiau linia rowIndex
ArrayList rand_cautat = (ArrayList) dateContinute.get(linie);
return rand_cautat.get(col);

public int getRowCount() {


187

return dateContinute.size();
// return date1Continute.size();
}

public int getColumnCount() {


return colNume.length;
}
public String getColumnName(int column) {
return colNume[column];
}

• la părăsirea controlului JComboBox se populează controalele cu datele cititorului şi


cărŃile deja împrumutate:

try {
// Se selecteaza codul autorului
int linie = cod_cititor.getSelectedIndex();
if (linie>=0){
rezultat_cititorii.absolute(linie+1); // mut cursorul in cited_rs pe linie
codcit = rezultat_cititorii.getInt("cod_cit");

// populez tabelul
Statement carti_stmt = null;
ResultSet rs = null;
try {
carti_stmt = cnx.createStatement();
String fraza;
fraza = "SELECT titlu, data_imprumut, data_rest FROM carti, cititori, imprumut";
fraza += " WHERE imprumut.cod_carte = carti.cod_carte ";
fraza += "and imprumut.cod_cit = cititori.cod_cit ";
fraza += "and cititori.cod_cit=" +codcit;
System.out.println(fraza);
rs = carti_stmt.executeQuery(fraza);

jTable1.setModel(new TbModel_3(rs));
carti_stmt.close();
// Redimensionez prima coloana
TableColumn coloana0 = null;
TableColumn coloana1 = null;
coloana0 = citcarti.getColumnModel().getColumn(0);
coloana1 = citcarti.getColumnModel().getColumn(1);
coloana0.setPreferredWidth(140);
coloana1.setPreferredWidth(80);
} catch (SQLException ex) {
ex.printStackTrace();
188

//populez textboxurile
try {
comanda = cnx.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
rezultat = comanda.executeQuery("SELECT nume, prenume, cnp FROM cititori
WHERE cod_cit="+codcit);
if (rezultat.next()) {
String sir1 = rezultat.getString("nume")+" "+ rezultat.getString("prenume");
String sir2 = rezultat.getString("cnp");
cititorul.setText(sir1);

cod_numeric.setText(sir2);
}

} catch (SQLException ex) {


ex.printStackTrace();

}
}
} catch (SQLException ex) {
ex.printStackTrace();
}

• pentru înregistararea unui nou împrumut preluaŃi codul cărŃii împrumutate astfel:

try {
// TODO add your handling code here:

int linie = cartea.getSelectedIndex();


if (linie>=0){
rezultat_cartile.absolute(linie+1);
codcarte = rezultat_cartile.getInt("cod_carte");

}
} catch (SQLException ex) {
ex.printStackTrace();
}

• la apăsarea butonului "Introducere" se adaugă o înregistrare în tabelul imprumut,


folosind codcit, codcarte şi data:
189

try {

String frazaSQL ;
frazaSQL = "INSERT into imprumut VALUES (" ;
frazaSQL += codcit + "," + codcarte + ","+ apostrof(dataimpr.getText())+",'')";

// Creez un Statement*/
Statement stm = cnx.createStatement();
// Apelez metoda executeUpdate() pt. a trimite comanda INSERT
stm.executeUpdate(frazaSQL);

stm.close();

//refac vederea din grid


Statement carti_stmt = null;
ResultSet rs = null;
try {
carti_stmt = cnx.createStatement();
String fraza;

fraza = "SELECT titlu, data_imprumut, data_rest FROM carti, cititori, imprumut";


fraza += " WHERE imprumut.cod_carte = carti.cod_carte ";
fraza += "and imprumut.cod_cit = cititori.cod_cit ";
fraza += "and cititori.cod_cit=" +codcit;

rs = carti_stmt.executeQuery(fraza);

jTable1.setModel(new TbModel_3(rs));
carti_stmt.close();
// Redimensionez prima coloana
TableColumn coloana0 = null;
TableColumn coloana1 = null;
coloana0 = citcarti.getColumnModel().getColumn(0);
coloana1 = citcarti.getColumnModel().getColumn(1);
coloana0.setPreferredWidth(140);
coloana1.setPreferredWidth(80);

} catch (SQLException ex) {


ex.printStackTrace();
}

//golesc capurile
cititorul.setText("");
cod_numeric.setText("");

} catch (SQLException ex) {


ex.printStackTrace();
}
190

7. CreaŃi un formular pentru efectuarea unei restituiri, astfel::

• la deschiderea formularului trebuie populate cu date cele două controale de tip


JComboBox, unul pentru lista codurilor cititorilor şi celălalt pentru lista cartilor din baza
de date:

try {
//populez lista cu codurile cititorilor
cititorii = cnx.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
rezultat_cititorii = cititorii.executeQuery("SELECT * from cititori order by cod_cit");

cod_cititor1.removeAllItems();
while (rezultat_cititorii.next()) {
String n = rezultat_cititorii.getString("cod_cit");
cod_cititor1.addItem(n);
}

//populez lista cu cartile


cartile = cnx.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
rezultat_cartile = cartile.executeQuery("SELECT * from carti order by titlu");

cartea1.removeAllItems();
while (rezultat_cartile.next()) {
String n = rezultat_cartile.getString("titlu");
cartea1.addItem(n);
}

// scriu data de azi in textbox


191

Calendar azi = Calendar.getInstance();


SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy");
datarest.setText(fmt.format(azi.getTime()));

} catch (SQLException ex) {


ex.printStackTrace();
}

ObservaŃie: după selectarea codului cititorului (ca şi în cazul formularului care înregiatrează
un împrmut), se execută mai multe acŃiuni:
a. se afişează datele de identificare ale acestuia în cele două controlae de tip
JTextField;
b. se populează controlul de tip JTable cu cărŃile împrumutate şi nerestituite (!) de
respectivul cititor.

• adăugaŃi aplicaŃiei o nouă clasă, TbModel_3_1 derivată din AbstractTableModel

public class TbModel_3_1 extends AbstractTableModel{


private String[] colNume={"Cartea","Data imprumutului"};
private ArrayList dateContinute; // va fi ArrayList de ArrayList

/** Creates a new instance of TbModel */


public TbModel_3_1(ResultSet rs) {
dateContinute = new ArrayList();

try{
while(rs.next()){
ArrayList linie = new ArrayList();
String cartea = rs.getString("titlu");
Date datai = rs.getDate("data_imprumut");
linie.add(cartea);
linie.add(datai);
dateContinute.add(linie);
}
} catch(Exception e){
System.out.println("Exceptie in TbModel");
}

public Object getValueAt(int linie, int col) {


// Preiau linia rowIndex
ArrayList rand_cautat = (ArrayList) dateContinute.get(linie);
192

return rand_cautat.get(col);

public int getRowCount() {


return dateContinute.size();
// return date1Continute.size();
}

public int getColumnCount() {


return colNume.length;
}
public String getColumnName(int column) {
return colNume[column];
}

• la părăsirea controlului JComboBox se populează controalele formularului:

try {
// Se selecteaza codul cititorului
int linie = cod_cititor1.getSelectedIndex();
if (linie>=0){
rezultat_cititorii.absolute(linie+1); // mut cursorul pe linie
codcit = rezultat_cititorii.getInt("cod_cit");

System.out.println(codcit);

// populez tabelul
Statement carti_stmt = null;
ResultSet rs = null;
try {
carti_stmt = cnx.createStatement();
String fraza;
fraza = "SELECT carti.titlu, imprumut.data_imprumut";
fraza += " FROM carti, cititori, imprumut";
fraza += " WHERE imprumut.cod_carte = carti.cod_carte ";
fraza += "and imprumut.cod_cit = cititori.cod_cit ";
fraza += "and imprumut.data_rest is null ";
fraza += "and cititori.cod_cit=" +codcit;
System.out.println(fraza);
rs = carti_stmt.executeQuery(fraza);
jTable2.setModel(new TbModel_3_1(rs));
carti_stmt.close();
// Redimensionez prima coloana
TableColumn coloana0 = null;
TableColumn coloana1 = null;
193

coloana0 = citcarti.getColumnModel().getColumn(0);
coloana1 = citcarti.getColumnModel().getColumn(1);
coloana0.setPreferredWidth(140);
coloana1.setPreferredWidth(80);

} catch (SQLException ex) {


ex.printStackTrace();
}
//populez textboxurile
try {
comanda = cnx.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
rezultat = comanda.executeQuery("SELECT nume, prenume, cnp FROM cititori
WHERE cod_cit="+codcit);
if (rezultat.next()) {
String sir1 = rezultat.getString("nume")+" "+ rezultat.getString("prenume");
String sir2 = rezultat.getString("cnp");
cititorul1.setText(sir1);
cod_numeric1.setText(sir2);
}

} catch (SQLException ex) {


ex.printStackTrace();

}
// //populez combo-ul cu cartile nerestituite
try {
carti_nerest = cnx.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
String fraza1;
fraza1 = "SELECT carti.titlu, carti.cod_carte ";
fraza1 += " FROM carti, cititori, imprumut";
fraza1 += " WHERE imprumut.cod_carte = carti.cod_carte ";
fraza1 += "and imprumut.cod_cit = cititori.cod_cit ";
fraza1 += "and imprumut.data_rest is null ";
fraza1 += "and cititori.cod_cit=" +codcit;
System.out.println(fraza1);
rs_nerest = carti_nerest.executeQuery(fraza1);

cartea1.removeAllItems();
while (rs_nerest.next()) {
String n = rs_nerest.getString("titlu");
cartea1.addItem(n);
}

} catch (SQLException ex) {


ex.printStackTrace();
194

}
}
} catch (SQLException ex) {
ex.printStackTrace();
}

• adăugaŃi clasei principale o variabilă, codcarte1 pentru preluarea codului cărŃii


restituite;
• după selectarea cărŃi restituite preluaŃi codul cărŃii:
try {
int linie = cartea1.getSelectedIndex();
if (linie>=0){
rs_nerest.absolute(linie+1);
codcarte1 = rs_nerest.getInt("cod_carte");

}
} catch (SQLException ex) {
ex.printStackTrace();
}
• la apăsarea butioului "Introducere" se caută înregistrarea cu codcit şi codcarte1 din
tabelul imprumut şi se trimite o frază UPDATE (data se preia din sistem):
try {

String fraza2SQL ;
fraza2SQL = "UPDATE imprumut SET data_rest =";
fraza2SQL += apostrof(datarest.getText()) ;
fraza2SQL += "WHERE cod_carte = "+ codcarte1 + " and cod_cit = "+codcit;

// Creez un Statement*/
Statement stm = cnx.createStatement();
// Apelez metoda executeUpdate() pt. a trimite comanda UPDATE
stm.executeUpdate(fraza2SQL);
stm.close();

//refac vederea din grid


Statement carti_stmt = null;
ResultSet rs = null;
try {
carti_stmt = cnx.createStatement();
String fraza;
fraza = "SELECT carti.titlu, imprumut.data_imprumut";
fraza += " FROM carti, cititori, imprumut";
fraza += " WHERE imprumut.cod_carte = carti.cod_carte ";
fraza += "and imprumut.cod_cit = cititori.cod_cit ";
fraza += "and imprumut.data_rest is null ";
195

fraza += "and cititori.cod_cit=" +codcit;


System.out.println(fraza);
rs = carti_stmt.executeQuery(fraza);

jTable2.setModel(new TbModel_3_1(rs));
carti_stmt.close();
// Redimensionez prima coloana
TableColumn coloana0 = null;
TableColumn coloana1 = null;
coloana0 = citcarti.getColumnModel().getColumn(0);
coloana1 = citcarti.getColumnModel().getColumn(1);
coloana0.setPreferredWidth(140);
coloana1.setPreferredWidth(80);

} catch (SQLException ex) {


ex.printStackTrace();
}
//golesc capurile
cititorul1.setText("");
cod_numeric1.setText("");

} catch (SQLException ex) {


ex.printStackTrace();
}
196

Laborator nr. 12

Rapoarte

1. PorniŃi aplicaŃia iReport2.0.1.


2. CreaŃi o conexiune cu OracleXE, baza biblio.
3. CreaŃi un raport simplu, care afişează informaŃii din tabelul Edituri :
• File -> Report Wizard
• selectaŃi conexiunea şi introduceŃi fraza SQL pe baza căreia se va realiza raportul:

• selectaŃi câmpurile care vor fi incluse în raport:


197

• selectaŃi criteriile de grupare (aici nu e cazul)

• stabiliŃi aspectul raportului

4. Raportul creat:

• rulaŃi raportul: Build -> Execute (with active connection) sau butonul
• salvaŃi raportul. Pentru aceasta creaŃi în directorul aplicaŃiei Java biblio subdirectorul
Rapoarte.
198

• vizualizaŃi raportul:

• modificaŃi aspectul (titlu propriu, redenumire coloane, font, culoarea font) folosind fereastra
de proprietăŃi;

5. CreaŃi o listă a cititorilor, grupaŃi pe localităŃi, afişaŃi în ordine alfabetică:


• raportul se bazează pe tabelul Cititori
199
200

• După ajustarea proprietăŃilor raportului un posibil rezultat:

6. CreaŃi o listă a cititorilor grupaŃi pe judeŃe şi apoi pe localităŃi:


• creaŃi în Oracle vederea :
CREATE OR REPLACE FORCE VIEW "VCITITORI" ("NUME", "PRENUME", "LOCALITATEA",
"ACRONIM") AS
select "CITITORI"."NUME" as "NUME",
"CITITORI"."PRENUME" as "PRENUME",
"CITITORI"."LOCALITATEA" as "LOCALITATEA",
"JUDET"."ACRONIM" as "ACRONIM"
from "JUDET" "JUDET",
"CITITORI" "CITITORI"
where "JUDET"."COD_JUD"="CITITORI"."COD_JUD"
order by JUDET.ACRONIM ASC, CITITORI.LOCALITATEA ASC !!!
• selectaŃi vederiea în Query Designer
201

• selectaŃi câmpurile vizibile:

• creaŃi două nivele de grupare:

• alegeŃi aspectul, salvaŃi şi vizualizaŃi raportul;

• După modificarea aspectului, un rezultat posibil ar fi următorul:

7. CreaŃi o listă a cărŃilor grupate pe edituri şi autori :


• raportul se bazează pe vederea vcarti:
select "CARTI"."TITLU" as "TITLU",
"EDITURI"."NUME" as "NUMEED",
"AUTORI"."NUME" as "NUME",
"AUTORI"."PRENUME" as "PRENUME"
from "AUTCARTI" "AUTCARTI",
"AUTORI" "AUTORI",
"EDITURI" "EDITURI",
"CARTI" "CARTI"
202

where "AUTCARTI"."COD_AUT"="AUTORI"."COD_AUT"
and "AUTCARTI"."COD_CARTE"="CARTI"."COD_CARTE"
and "EDITURI"."COD_EDIT"="CARTI"."COD_EDIT"
order by CARTI.TITLU ASC, EDITURI.NUME ASC, AUTORI.NUME ASC !!!
După gruparea pe trei nivele, alegerea aspectului, salvarea şi vizualizarea raportului un rezultat
posibil ar fi următorul:

8. IntegraŃi rapoartele în proiectul Dv. urmărind paşii din curs.

S-ar putea să vă placă și