Tải bản đầy đủ - 0 (trang)
Chapter 11. Using XML in Reporting Systems

Chapter 11. Using XML in Reporting Systems

Tải bản đầy đủ - 0trang

Chapter11.UsingXMLinReporting

Systems

INTHISCHAPTER

ArchitectureofReportingSystems

WhentoUseXMLwithReports

DataSourceforReports

ResultSettoXML

BringingItAllTogether

TheSortingTableStylesheet

TheCrossTabStylesheet

Summary

NomatterwhattheWebapplication,orwhereit'simplemented,it'sasafebetto

assumethattherewillbesomereportinginvolved.Evenapplicationsthatdon't

havedatabasesarelikelytohavesomeaspectofreporting.However,nondatabasesystemsaremorelikelytobelookingatreportsregardingnumbersof

pageusageanddataexclusivetosystemusage.Thedevelopmentofeitherof

thesereportingsystemscanbenefitfromtheappropriateplacementandusageof

XML.

AftercreatingaJSPthatwillfillthedatabasewithasmuchdataasneeded,

JDOMandXSLwillbeusedtocreatetworeports.Beforeexplainingthose

reportcomponents,wewillexplainaJavaclassthatbuildsaJDOMXML

representationfromadatabaseResultSet.



ArchitectureofReportingSystems

Thedifferenttypesofreportingsystemsthatexisthavetodomostnotablywith

thetypesofreportstocreate,andthestructureoftheentiresystem.Themain

typesofreportsaretables,crosstabs,andaggregate.Ourfirststylesheetwill

createaverygenerictable-creatingstylesheetwithdynamicsortinglabellinks,

whilethesecondstylesheetwillcreateacrosstabreportfromthesamedata



source.

Thisbringsusintotheoverallreportingsystemstructure.Theidealsystem

wouldhavedatabase-storedproceduresperformtheinitialfilteringandsorting

ofdata,andhavestylesheetsthatwouldeachproduceseveralreports.One

stylesheetcanproducemultiplereportsbyusingstylesheetparametersand

changingfilteringorsortingmethods.

Evenmoreideally,thesestylesheetswouldbecreatedgenericallyenoughtobe

usableonmultipledatasets.Inthisway,averyrobustreportingsystemcanbe

createdquickly,afterwhichthemorespecific,data-dependentreportscanbe

created.

Anotherthingtoconsiderwhencreatingreportingsystemshastodowith

securityandaccessrights.Differentpeoplewillbepermittedtoseeonlysome

reports,anditisimportanttoincorporateasimplemodeltomaintainthis

security.Acommondesignistohaveadatabasetablethatcontainsarecordfor

eachreport.Thenanothertablewillhavearecordforeachreportandlogintype

thathasaccesstoit.Inthisway,itissimpletochangeaccessrightstoreports

withouthavingtotouchthereportingpagesthemselves.

Thereportingexamplesthroughoutthischapterandthenextwilluseadatabase

fromwhichtocreatetheJDOMdocumentsthatwillbetransformedwitha

genericstylesheetintoourresultingHTMLoutputpage.Wewillgluethese

piecestogetherusingaJSPtodothetransformationandfinallyoutputthe

results.ItisrelativelysimpletochangethebackendandcreatetheJDOM

documentfromanothersource.



WhentoUseXMLwithReports

XMLisnotalwaystheproperchoiceinreportingsystems.Itmustbeunderstood

thatitsuseincludesanextralayerofprocessingbeyondjustprogrammatically

convertingadatabaseResultSetintotheoutputdesired.Thedifference

residesinthespeedatwhichthesesystemscanbebuiltbecause,ifcarefully

created,thestylesheetsarereusableacrossdatasets,andfewerstoredprocedures

havetobecreated.

DOMdocumentmodelsconsumememoryproportionaltothesizeand



complexityofthedatasetsbeingmodeled.Databasedatawillmaintainthesame

complexityacrossResultSets,butcanbeextremelylarge.Thesizeofthe

datasetsbeingusedtocreateJDOMsmustbeconsideredwhencreatingthese

systems,orsometroubleswillresult.

Inthenextchapteranexampleofapagingreportwillbedemonstrated.This

reportwillonlydisplayasetmaximumnumberofrecordsperpage,butitwill

createlinksthatenabletherestofthedatatobeseenondifferent"pages"ofthe

samereport.Thisisonemethodofhandlingpotentiallylargedatasets.Another

methodiswritingJavaBeansthatwilliteratethroughtheResultSetto

createthedesiredoutput.Inthisway,thememorylimitationsofDOMwillbe

avoided.

WhileSAXcanbeveryusefulinsomereportingsituationswherethereisalarge

amountofsimilarlyformatteddata,wearenotusingithere.Thisisbecausewe

areusingtheXSLsortingcapabilitiesinsteadofsortingthedataatthedatabase.



DataSourceforReports

Thedatasourcefortheexamplesinthisandthefollowingchapterscomefrom

twotablesinthexmlbookdatabasecreatedinAppendixA,"SettingUp."The

datainthesetablescontainssomeverybasicinformationaboutclinicpatients

andtheirhealthailments.ThesetablesareReportClientDataand

ReportClientAilmentandbetweenthemthereisaone-to-manyrelationships.

Thatis,foreachpatientinReportClientData,theremightbemultipleailment

recordsinReportClientAilment.Thisrelationshipwascreated,andwillbeused

inthenexttwochapters,toaidindemonstratingstylesheetmethodsfordealing

withthesetypesofdatarelationships.



CreatingDatabaseData

Thefirstthingthatmustbedoneistopopulatethetwopreviouslymentioned

tableswithdata.AJSPhasbeencreatedtocreateasmanyrecordsasare

necessaryforthispurpose,anditsdescriptionfollows.ThisJSPcontainsa

simpleformthatallowstheusertoenterthenumberofclientrecordstobe

created.



Whentheformissubmitted,thesameJSPwillbeginbycreatingtherequested

numberofclientrecords.Aseachclientrecordiscreated,arandomnumberof

ailmentrecordsarecreatedcorrespondingtothatclientrecord.

TheJSPnamedCreateDBData.jspfoundinListing11.1beginswithanimport

statementandthesmallHTMLformthatallowstheusertoenterthenumberof

rowsofdatathatarecreated.Next,thevariablesareset,andtheparameter

enteredthroughtheformisparsedthroughatry-catchblockasfollows:



try{

client_rows=Integer.parseInt(request.getParameter

}

//catchanyandallerrorswithformdata

catch(NumberFormatExceptione){

client_rows=0;

}

Ifanyerrorsresultfromtheparsingoftheformvariable,suchasanonexistent

valueoranon-integervalue,theparameterissetto0intheprecedingcatch

block.Thiswillpreventthecreationofanynewrecords.

AftercreatingourdatabaseConnectionandStatementobjects,the

loopingconstructthatwillinsertclientrecordsintothedatabasebegins:



for(inti=0;i
db_statement.execute(createQueryClient());

ResultSetrs=db_statement.executeQuery("selectLA

rs.last();

intlast_insert_id=rs.getInt(1);

Eachiterationoftheprecedingforloopwillinsertonerecordintothe

ReportClientDatatable.Afterwhich,astatementisexecuted,andtheresulting

ResultSetistraversedtofindtheidentityvalueofthenewlyinserted

record.

Thisidentityvalueisusedtokeyailmentrecordswithaclientrecord.The



identityvalueofthecorrespondingclientrecordwillbecontainedineach

ailmentrecord.Thiswillresultaone-client-to-many-ailmentsrelationshipthat

willbeusedinthefollowingreportingchapter.

Next,arandomnumberisgeneratedtodeterminehowmanyailmentrecords

willbecreatedforthecurrentclient.Thisnumberisusedtoloopthroughthe

creationofeachailmentrecord:



intclient_ailment=(int)(Math.random()*5);

for(intk=0;k
try{

db_statement.execute(createQueryAilment(last_ins

out.print("
Ailmentaddedforrecordindex:

last_insert_id+".With"+(k+1)+"outo

client_ailment+"Records.");

ailment_rows++;

}catch(SQLExceptione){

out.print("
Ailmentskippedforrecordin

last_insert_id+".Duetoduplicate.");

}

}

Theprocessingofthesestatementsiswrappedinatry-catchblockto

enablethehandlingofSQLExceptions.Allthedataiscreatedrandomly,

andthiscausestheoccasionalduplicateailmentrecordtobecreated.Duplicates

areunacceptableinthistablebecauseeachclientcanonlyhaveonerecord

indicatinganailment.Thisduplicationerrorishandledintheprecedingcatch

block,andpermitstherestoftheprocessingtocontinue.

Nextisthecodethatoutputsstatusstatementsandcatchblockstocatchthe

variousexceptionsthatthepreviousstatementscancreate.Thepagedeclaration

followstheendofthescriptlet.

Thisiswherethemethodsthatcreateourdates,names,andotherrecorddata

reside.Followingthesearethemethodsthatbringitalltogethertocreatethe

completeinsertstatementsexecutedagainstthedatabase.



ThecompleteJSPthatwilldynamicallycreateandinsertdatacanbefoundin

Listing11.1andshouldbesavedas

\webapps\xmlbook\chapter11\CreateDBData.jsp.

Listing11.1CreateDBData.jspinItsCompleteForm



<%@pageimport="java.sql.*"%>















Numberofrowstocreate:




















<%

//1.Initializevariables

intclient_rows;

Stringfinal_status="Therewere0ClientDatar

Stringdb_query="";

Stringdb_location="jdbc:mysql://localhost/xml

Stringdb_driver="org.gjt.mm.mysql.Driver";



intailment_rows=0;



try{

client_rows=Integer.parseInt(request.getParam

}

//catchanyandallerrorswithformdata

catch(NumberFormatExceptione){

client_rows=0;

}



//2.Makeadatabaseconnection

Connectiondb_connection=null;

try{

Class.forName(db_driver);

db_connection=DriverManager.getConnection(db_

Statementdb_statement=db_connection.createSt



//3.CreaterecordsforReportClientDatatablein

for(inti=0;i
db_statement.execute(createQueryClient());

ResultSetrs=db_statement.executeQuery

("selectLAST_INSERT_ID()");

rs.last();

intlast_insert_id=rs.getInt(1);

intclient_ailment=(int)(Math.random()*

for(intk=0;k
try{

db_statement.execute(createQueryAil

out.print("
Ailmentaddedfor

last_insert_id+".With"+(k

client_ailment+"Records.");

ailment_rows++;

}catch(SQLExceptione){



out.print("
Ailmentskippedfo

last_insert_id+".Duetodupl

}

}

if(client_rows-1==i)

final_status="Therewere"+client_r

"ClientDatarecordsadded.";

}



}

catch(ClassNotFoundExceptione)

{final_status="Errorcreatingdatabasedrive

final_status+="
"+e.toString();

}

catch(SQLExceptione)

{final_status="ErrorprocessingtheSQL!";

final_status+="
"+e.toString();

}

finally

{

/*Wemustclosethedatabaseconnectionnow*/

try

{if(db_connection!=null)

{db_connection.close();}

}

catch(SQLExceptione)

{final_status="Errorinclosingconnectio

final_status+="
"+e.toString();

}

}

%>







<%=final_status%>


And<%=ailment_rows%>AilmentDatarecordsad













<%!

charletters[]={'a','b','c','d','e','f',

'g','h','i','j','k','l','m','n','o',

'p','q','r','s','t','u','v','w','x','y','

privateStringcreateString(intlength){

Stringresult="";



for(inti=0;i
inttemp=(int)(Math.random()*26);

//capitalizethefirstletterinthisstring

if(i==0)

result+=Character.toUpperCase(letters[tem

else

result+=letters[temp];

}

returnnewString(result);

}

//1meansbirthdate(1930-1996)

//2meansailment10years(1980-1997)

privateStringcreateDate(intyear_range){

Stringresult="19";



if(year_range==1)

result+=""+(30+(int)(Math.random()*67)

else

result+=""+(80+(int)(Math.random()*18)

result+="-"+(1+(int)(Math.random()*12));

result+="-"+(1+(int)(Math.random()*28));

returnnewString(result);

}

privateStringcreateColor(){

Stringresult="";

intpick_a_color=(int)(Math.random()*6);

switch(pick_a_color){

case0:result="red";

break;

case1:result="yellow";

break;

case2:result="blue";

break;

case3:result="green";

break;

case4:result="purple";

break;

case5:result="orange";

break;

default:result="black";

}

returnresult;

}



privateStringcreateQueryClient(){

Stringdb_query="insertintoReportClientData"

db_query+="(RCD_lname,RCD_fname,RCD_clinic,RCD_do

db_query+="values(";

db_query+="'"+createString(7)+"',";

db_query+="'"+createString(5)+"',";

db_query+="'"+(1+(int)(Math.random()*5))+

db_query+="'"+createDate(1)+"',";

db_query+="'"+createColor()+"')";

returndb_query;

}

privateStringcreateQueryAilment(intclientID){



Stringdb_query="insertintoReportClientAilmen

db_query+="(RCA_medicalailment,RCA_datefound,RCA_

db_query+="values(";

db_query+="'"+createString(1)+"',";

db_query+="'"+createDate(2)+"',";

db_query+="'"+clientID+"')";

returndb_query;

}

%>

Nowthatsomedataexists,let'sstartcreatingsomereports.Thefirststepinthis

processiscreatingaclassthatwillcreateaJDOMrepresentationoutofa

ResultSet.



ResultSettoXML

RStoXMLisaclassthatwillreturnaJDOMrepresentationofadatabase