Tải bản đầy đủ - 0 (trang)
Hack 24. Create a JDBC Table Model

Hack 24. Create a JDBC Table Model

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

variousjava.sqlinterfaces.

AURLwithwhichtoconnecttothedatabase.Thisimplies

theuseofsockets,thoughthat'snotnecessarilythecase.

Somesmallembeddabledatabasescanliveinthesame

JVMasyourapplication.

Anoptionalusername.

Anoptionalpassword.

OnceyouhavetheConnection,youcanbegintosendcommands

(creation,deletion,andalteringoftables)orqueriestothe

databasebycreatingStatementsfromtheConnection.Youcanalso

usetheConnectiontogetmetadataaboutthedatabase,likewhat

kindsoffeaturesitsupports,howlongcertainstringscanbe,

etc.Moreimportantlyforthishack,itallowsyoutodiscover

whattablesareinthedatabase,whatcolumnstheyhave,and

whattypesofdataareinthosecolumns.

So,givenjustaConnectionandthenameofatableinthe

database,youcanbuildaJavarepresentationofitscontents

withtwoqueries.Thefirstquerygetscolumnmetadataforthe

tableandbuildsuparraysofthecolumnnamesandtheirtypes.

ThesecanbemappedreasonablywelltoJavaclasses,atleast

forwhatevertypesyouintendtosupport.Thesecondquery

getsallthedatafromthetable.Foreachrow,itgetseach

column'svalue.Thisisputintoatwo-dimensionalarray,which

representstheentirecontentsofthetable.

Withthesetwoqueriesdone,youhaveeverythingyouneedto

supporttheabstractmethodsofAbstractTableModel:

getRowCount()isthelengthofthecontentsarraythatyou



create.



getColumnCount()is0ifyouhavenocontents,orthelengthof



thefirstiteminthecontentsarray(whichisitselfanarray

becausecontentsisatwo-dimensionalarray).

getValueAt()isthevalueatcontents[row][col].

AbstractTableModelhasutterlytrivialimplementationsof

getColumnClass()andgetColumnName(),sothefirstalwaysreturns

Object.class,thesecondreturns"A","B","C",etc.;holdingonto



columnmetadatafromthefirstqueryallowsyoutoprovide

moreusefulimplementationsofthesemethods,too.

Example3-12showshowtheJDBCTableModelisimplemented.



Example3-12.PopulatingaSwingTableModel

fromadatabaseconnection

























importjavax.swing.*;

importjavax.swing.table.*;

importjava.sql.*;

importjava.util.*;

/**animmutabletablemodelbuiltfromgetting



metadataaboutatableinajdbcdatabase

*/

publicclassJDBCTableModelextendsAbstractTableModel



Object[][]contents;



String[]columnNames;



Class[]columnClasses;



























publicJDBCTableModel(Connectionconn,





StringtableName)



throwsSQLException{



super();



getTableContents(conn,tableName);























}

protectedvoidgetTableContents(Connectioncon







StringtableName)



throwsSQLException{







































































































































//getmetadata:whatcolumnsexistandwhat

//types(classes)arethey?

DatabaseMetaDatameta=conn.getMetaData();

System.out.println("gotmeta="+meta);

ResultSetresults=



meta.getColumns(null,null,tableName,

System.out.println("gotcolumnresults");

ArrayListcolNamesList=newArrayList();

ArrayListcolClassesList=newArrayList();

while(results.next()){



colNamesList.add(results.getString("C



System.out.println("name:"+





results.getString("COLUMN_NAME



intdbType=results.getInt("DATA_TYPE



switch(dbType){



caseTypes.INTEGER:

colClassesList.add(Integer.class);break;



caseTypes.FLOAT:

colClassesList.add(Float.class);break;



caseTypes.DOUBLE:



caseTypes.REAL:

colClassesList.add(Double.class);break;



caseTypes.DATE:



caseTypes.TIME:



caseTypes.TIMESTAMP:

colClassesList.add(java.sql.Date.class);break



default:

colClassesList.add(String.class);break;



};



System.out.println("type:"+





results.getInt("DATA_TYPE"));



}



















































columnNames=newString[colNamesList.

colNamesList.toArray(columnNames);

columnClasses=newClass[colClassesLi

colClassesList.toArray(columnClasses);













































Statementstatement=

conn.createStatement();



results=statement.executeQuery("SELE









tableName);



ArrayListrowList=newArrayList();



while(results.next()){

ArrayListcellList=newArrayList();

for(inti=0;i


ObjectcellValue=null;

















































































if(columnClasses[i]==String.class)

cellValue=results.getString(columnNames[i]);



elseif(columnClasses[i]==Integer.cl

cellValue=newInteger(





results.getInt(columnNames[i])



elseif(columnClasses[i]==Float.clas

cellValue=newFloat(





results.getInt(columnNames[i])



elseif(columnClasses[i]==Double.cla

cellValue=newDouble(





results.getDouble(columnNames[



elseif(columnClasses[i]==java.sql.D

cellValue=results.getDate(columnNames[i]);



else

System.out.println("Can'tassign"+





columnNames[i]);



cellList.add(cellValue);

}//for



//getalldatafromtableandputinto

//contentsarray





















Object[]cells=cellList.toArray();



rowList.add(cells);



}//while

//finallycreatecontentstwo-dimarray

contents=newObject[rowList.size()][];

for(inti=0;i












contents[i]=(Object[])rowList.get(i);

System.out.println("Createdmodelwith"+





contents.length+"rows");











//closestuff

results.close();

statement.close();















}

//AbstractTableModelmethods

publicintgetRowCount(){



returncontents.length;

}

















publicintgetColumnCount(){



if(contents.length==0)





return0;



else





returncontents[0].length;



}



















publicObjectgetValueAt(introw,intcolumn)



returncontents[row][column];

}















//overridesmethodsforwhichAbstractTableMod

//hastrivialimplementations











publicClassgetColumnClass(intcol){

















}



returncolumnClasses[col];



















}



publicStringgetColumnName(intcol){



returncolumnNames[col];

}



TheconstructordumpsoffitsrealworktogetTableContents(),

whichisresponsibleforthetwoqueriesjustdescribed.Itgetsa

DatabaseMetaDataobjectfromtheConnection,fromwhichyoucan

thengetthecolumndatawithagetColumns()call.Thearguments

tothismethodarethecatalog,schemapattern,tablename

pattern,andcolumnnamepattern;thisimplementationignores

catalogsandschema,althoughyoumightneedtohavecallers

specifythemifyouhaveacomplexdatabase.getColumns()

returnsaResultSet,whichyouiterateoverjustlikeyouwould

withtheresultsofaregularJDBCquery.

Gettingthecolumnnameiseasy:justcall

getString("COLUMN_NAME").Thetypeisalittlemoreinteresting,as

thegetInt("DATA_TYPE")callwillreturnanint,whichrepresents

oneoftheconstantsofthejava.sql.Typesclass.Inthisexample,

I'vesimplymappedStringsandthebasicnumbertypesto

appropriateJavaclasses.TIMESTAMPisSQL'sconceptofapointin

time(aDATEandaTIME),soitgetstobeaJavaDate.Knowing

thesetypeswillmakeiteasiertocalltherightgetXXX()method

whenretrievingtheactualtabledata.

ThesecondqueryisasimpleSELECT*FROMtableName.Withno

WHERErestrictiononthequery,thiswillcreateaResultSetwith

everyrowinthetable.Ishouldn'thavetomentionthatif

tableNameisatablewithmillionsofrecords,yourresulting

TableModelisnotgoingtofitintomemory.Youknewthat,right?



Again,youneedtoiterateoveraResultSet.Eachtimethat

results.next()returnstrue,meaningthere'sanotherresult,you

pullouteverycolumnyouknowaboutfromtheearlier

metadataquery.ThismeanscallingagetXXX()methodand

passinginthecolumnname,whereyouknowwhichgetXXX()to

usefromyourearlierinvestigationofthetypeofeachcolumn.

Youcangoaheadandputnumericdataintoitsproperwrapper

class(Integer,Double,etc.)becausethatworkswellwiththe

class-basedrenderingsystemofJTables.Acallermightdecideto

useaTableCellRendererthatappliesaFormatclasstoallDoublesin

thetabletodisplaythemonlytoacertainnumberofdecimal

points,ortorenderDateswithrelativetermslike"Today"and

"25hoursago."Stronglytypingthedatainyourmodelwillhelp

withthat.

Withthequeriesdone,youjustconverttheArrayListstoreal

arrays(whichofferquicklookupsforthegetmethods).The

implementationsoftheAbstractTableModelmethodsmentioned

previously,aswellastheimprovedimplementationsof

getColumnClass()andgetColumnName(),aretrivialusesofthe

columnNames,columnClasses,andcontentsarraysbuiltupbythis

method.



3.5.2.TestingThingsOut

Beforeyousay"Ican'trunthishack,Idon'thaveadatabase,"

relax!Theopensourceworldhasyoucovered.Andno,it'snot

somebigthinglikeJBoss.HSQLDB,morecommonlyknownby

itsoldname,Hypersonic,isaJDBCrelationaldatabaseengine

writteninJava.Itisreallysmallandcanberunasastandalone

serverorwithinyourJVM.Ifyouaredatabase-less,grab

HSQLDBfromhttp://hsqldb.sourceforge.net/.

Whateveryourdatabase,you'llneedadriverclassname,URL,

username,andpasswordtomakeaconnectiontothedatabase.

Ifyouhaveyourowndatabase,Itrustyoualreadyknowthis.If



youjustdownloadedHSQLDBoneparagraphago,thenyou'llbe

usingthefollowinginformation:

Driver:org.hsqldb.jdbcDriver

URL:jdbc:hsqldb:file:testdb

User:sa

Password:(none)

Thisassumesyou'llberunningHypersonicaspartofyour

application,meaningyou'llneedtoextendyourclasspathto

pickupthehsqldb.jarfile.Alsonotethatthiswillcreatesome

testdbfilesinyourcurrentdirectorythatyoucancleanupwhen

done.Youcanalsoprovideafullpathtosomeotherdirectory;

seeHSQLDB'sdocsformoreinfo.

Thetestrunnerexpectstopickuptheconnectionstringsas

propertiesnamedjdbctable.driver,jdbctable.url,jdbctable.user,

andjdbctable.pass.Tomakethingseasier,therearetwowaysto

passthesein:eitherassystemproperties(usuallyspecified

with-Dargumentstothejavacommand),orinafilecalled

jdbctable.properties.Thebookcodehasasampleofthelatter

withHSQLDBvaluesasdefaults.

TotesttheJDBCTableModel,theTestJDBCTablecreatesanentirely

newtableinthedatabase.ThemodelgetstheConnectionandthe

nameofthistableandloadsthedatafromthedatabase.Then

thetestclasssimplycreatesanewJTablefromthemodeland

putsitinaJFrame.Example3-13showsthesourceforthis

demo.



Example3-13.TestingtheJDBC-basedtable























importjavax.swing.*;

importjavax.swing.table.*;

importjava.sql.*;

importjava.util.*;

importjava.io.*;

publicclassTestJDBCTable{



publicstaticvoidmain(String[]args){





try{



























































/*

driver,url,user,andpasscanbepassedina

systemproperties"jdbctable.driver",

"jdbctable.url","jdbctable.user",and

"jdbctable.pass",orspecifiedinafile

called"jdbctable.properties"incurrent

directory

*/

PropertiestestProps=newProperties();

Stringddriver=System.getProperty("jdbctable

Stringdurl=System.getProperty("jdbctable.ur

Stringduser=System.getProperty("jdbctable.u

Stringdpass=System.getProperty("jdbctable.p



























































if(ddriver!=null)



testProps.setProperty("jdbctable.drive

if(durl!=null)



testProps.setProperty("jdbctable.url",

if(duser!=null)



testProps.setProperty("jdbctable.user"

if(dpass!=null)



testProps.setProperty("jdbctable.pass"

try{



testProps.load(newFileInputStream(







newFile("jdbctable.pr

}catch(Exceptione){}//ignoreFNF,etc.

System.out.println("TestProperties:");



















































testProps.list(System.out);

//nowgetaconnection

//notecaretoreplacenullswithemptystring

Class.forName(testProps.getProperty





("jdbctable.driver")).newInstan

Stringurl=testProps.getProperty("jdbctable.

url=((url==null)?"":url);

Stringuser=testProps.getProperty("jdbctable

user=((user==null)?"":user);

Stringpass=testProps.getProperty("jdbctable

pass=((pass==null)?"":pass);























Connectionconn=



DriverManager.getConnection(url,user,

//createdbtabletouse

StringtableName=createSampleTable(conn);























































//getamodelforthisdbtableandaddtoaJ

TableModelmod=



newJDBCTableModel(conn,tableName);

JTablejtable=newJTable(mod);

JScrollPanescroller=



newJScrollPane(jtable,





ScrollPaneConstants.VERTICAL_SC





ScrollPaneConstants.HORIZONTAL_

JFrameframe=newJFrame("JDBCTableModeldemo

frame.getContentPane().add(scroller);

frame.pack();

frame.setVisible(true);











conn.close();

























}catch(Exceptione){

e.printStackTrace();



}

}















publicstaticStringcreateSampleTable(Connect



throwsSQLException{



































































































statement.execute("DROPTABLEEMPLOYEES");



}catch(SQLExceptionsqle){

sqle.printStackTrace();//iftable!exists



}





statement.execute("CREATETABLEEMPLOY





"(NameCHAR(20),TitleCHAR(



statement.execute("INSERTINTOEMPLOYE





"('Jill','CEO',200000)");



statement.execute("INSERTINTOEMPLOYE





"('Bob','VP',195000)");



statement.execute("INSERTINTOEMPLOYE





"('Omar','VP',190000)



statement.execute("INSERTINTOEMPLOYE





"('Amy','SoftwareEngineer'



statement.execute("INSERTINTOEMPLOYE





"('Greg','SoftwareEngineer













statement.close();



return"EMPLOYEES";



}

}



Statementstatement=conn.createStatem

//droptableifitexists

try{



ThecreateSampleTable()methodissomethingyoucouldrewriteto

insertyourowntypesandvalueseasily.Infact,becauseit

returnsthenameofthetableyou'vecreated,youcouldcreate

manydifferenttablesinyourdatabaseandtestouthowthe

modelhandlesthem.Or,usealooptocreatelotsofrowsand



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Hack 24. Create a JDBC Table Model

Tải bản đầy đủ ngay(0 tr)

×