Upload
haoyuan-liu
View
40
Download
1
Embed Size (px)
DESCRIPTION
about java, sql, and jooq
Citation preview
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 1/48
Java,SQLandjOOQ.
BestPracticesandLessonsLearnedfromWritingAwesomeJavaandSQLCode.GetsomehandsoninsightonwhatsbehinddevelopingjOOQ.
Archive|javaRSSforthissection
injava,sqlLeaveacomment
jOOQvs.Hibernate:WhentoChooseWhich
HibernatehasbecomeadefactostandardintheJavaecosystem,andafterthefact,alsoanactualJavaEEstandardimplementationifstandardsmattertoyou(http://xkcd.com/927),andifyouputtheJCPonthesamelevelwithISO,ANSI,IEEE,etc.
Thisarticledoesnotintendedtodiscussstandards,butvisions.Hibernate(http://hibernate.org)sharesJPAsvisionofORM.jOOQ(http://www.jooq.org)sharesSQLsvisionofpowerfulquerying,soforthesakeoftheargument,letsuseHibernate/JPA/ORMinterchangeably,muchlikejOOQ/JDBC/SQL.
ThequestionwhyshouldanyonenotuseHibernatethesedaysalwaysshowsupfrequently(https://groups.google.com/forum/#!topic/jooquser/gmBf6g6sdQA)preciselybecauseHibernateisadefactostandard,andthefirstframeworkchoiceinmanyotherframeworkssuchasGrails(whichusesGORM,whichagainusesHibernate(https://grails.github.io/grailsdoc/latest/guide/GORM.html)).
However,evenGavinKing,thecreatorofHibernate,doesntbelievethatHibernateshouldbeusedforeverything:
(https://plus.google.com/+GavinKing/posts/LGJU1NorAvY)
Ifthatsthecase,arethereanyobjectivedecisionhelpingpointsthatyoucouldconsider,whentouseanORMandwhentouseSQL?
Discussingonahighlevel
March24,2015
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 2/48
Firstoff,letsbringthisdiscussiontoahigherlevel.InsteadofdecidingbetweenHibernateandjOOQasconcreteimplementationsoftheirowndomains,letsthinkaboutORMvs.SQL,andtheirdifferentusecases.
WhendecidingbetweenanORM(e.g.Hibernate)andSQL(e.g.jOOQ),thedrivingquestionthatyoushouldaskyourselfisnotthequestionofprojectcomplexity.SomeofourmostdemandingcustomersareusingjOOQonmediumsizedschemaswiththousandsoftables/views.Often,thoseschemasareextremelynormalisedandsometimesevendeployedonasmanyassixdifferentRDBMS.jOOQwasspecificallydesignedtoworkinthesescenarios,whilekeepingthesimpleusecaseinmindaswell.
So,insteadofthinkingaboutprojectcomplexity,askyourselfthefollowingquestions:
1.Willyourdatamodeldriveyourapplicationdesign,orwillyourapplicationdesigndriveyourdatamodel(s)?Amainaspecthereisthequestionwhetheryoucareaboutyourdatabaseinthesenseofwhetheritmightsurviveyourapplication.Veryoften,applicationscomeandgo.TheymayberewritteninPython/JavaScript,etc.5yearsdowntheline.Oryouhavemultipleapplicationsaccessingthesamedatabase:YourJavaapplication,somePerlscripts,storedprocedures,etc.Ifthisisthecase,databasedesignisapriorityinyourproject,andjOOQworksextremelywellinthesesetups.
IfyoudontnecessarilycareaboutyourdatabaseinthesensethatyoujustwanttopersistyourJavadomainsomewhere,andthishappenstobearelationaldatabase,thenHibernatemightbeabetterchoiceatleastinearlystagesofyourproject,becauseyoucaneasilygenerateyourdatabaseschemafromyourEntitymodel.
2.Willyoudomostlycomplexreadingandsimplewriting,orwillyouengageincomplexwriting?SQLreallyshineswhenreadingiscomplex.Whenyoujoinmanytables,whenyouaggregatedatainyourdatabase,whenyoudoreporting,whenyoudobulkreadingandwriting.Youthinkofyourdataintermsofsettheory,e.g.yourdataasawhole.WritingCRUDwithSQLisboring,though.ThisiswhyjOOQalsoprovidesyouwithanActiveRecordstyleAPIthathandlestheboringparts,whenyoureoperatingonsingletables(Jasonmentionedthis).
If,however,yourwritingbecomescomplex,i.e.youhavetoloadacomplexobjectgraphwith20entitiesinvolvedintomemory,performoptimisticlockingonit,modifyitinmanydifferentwaysandthenpersistitagaininonego,thenSQL/jOOQwillnothelpyou.ThisiswhatHibernatehasoriginallybeencreatedfor.
Opinion
Ibelievethatdataisforever.Youshould*always*assumethatyourdatabasesurvivesyourapplication.Itismucheasiertorewrite(partsof)anapplicationthantomigrateadatabase.Havingacleanandwelldesigneddatabaseschemawillalwayspayoffdownthelineofaproject,specificallyofacomplexproject.Seealsoourpreviousarticleaboutthefallacyofschemalessdatabases(http://blog.jooq.org/2014/10/20/stopclaimingthatyoureusingaschemalessdatabase/).
Also,mostprojectsreallydo90%readingand10%writing,writingoftennotbeingcomplex(23tablesmodifiedwithinatransaction).Thismeansthatmostofthetime,thecomplexitysolvedbyHibernate/JPAsfirstandsecondlevelcachesisnotneeded.Peopleoftenmisunderstandthesefeaturesandsimplyturnoffcaching,flushingHibernatescachetotheserverallthetime,andthususingHibernateinthewrongway.
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 3/48
If,however,youreundecidedabouttheabovetwoaxesofdecision,youcangothemiddlewayandusejOOQonlyforreporting,batchprocessing,etc.anduseHibernateforyourCRUDinaCQRS(CommandQueryResponsibilitySegregation:http://martinfowler.com/bliki/CQRS.html(http://martinfowler.com/bliki/CQRS.html))style.TherearealsoquiteafewjOOQuserswhohavechosenthispath.
Furtherreading
Throughputvs.ComplexityWhenshouldIuseanORM?(http://mikehadlow.blogspot.ca/2012/06/whenshouldiuseorm.html)byMikeHadlowWhyshouldyouuseanORM?(http://karwin.blogspot.ch/2009/01/whyshouldyouuseorm.html)byBillKarwinArethereanygoodreasonsnottouseanORM?(http://stackoverflow.com/q/194147/521799)onStackOverflowWhyshouldyouuseanORM?(http://stackoverflow.com/q/448684/521799)onStackOverflow
injava,java82Comments
10JavaArticlesEveryoneMustRead
Onemonthago,wevepublishedalistof10SQLArticlesEveryoneMustRead(http://blog.jooq.org/2015/02/13/10sqlarticleseveryonemustread/).AlistofarticlesthatwebelievewouldaddexceptionalvaluetoourreadersonthejOOQblog(http://blog.jooq.org).ThejOOQblogisablogfocusingonbothJavaandSQL,soitisonlynaturalthattoday,onemonthlater,werepublishinganequallyexcitinglistof10Javaarticleseveryonemustread.
Notethatbymustread,wemaynotspecificallymeantheparticularlinkedarticleonly,butalsootherworksfromthesameauthors,whohavebeenregularbloggersoverthepastyearsandneverfailedtoproducenewinterestingcontent!
Heregoes
1.BrianGoetz:Stewardship:theSoberingParts
ThefirstblogpostisactuallynotablogpostbutarecordingofaveryinterestingtalkbyBrianGoetzonOraclesstewardshipofJava.OnthejOOQblog,wevebeenslightlycriticalabout12featuresoftheJavalanguageinthepast,e.g.whencomparingittoScala(http://blog.jooq.org/2014/08/01/the10mostannoying
March13,2015
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 4/48
thingscomingbacktojavaaftersomedaysofscala/),orCeylon(http://blog.jooq.org/2013/12/03/top10ceylonlanguagefeaturesiwishwehadinjava/).
BrianmakesgoodpointsaboutwhyitwouldnotbeagoodideaforJavatobecomejustasmodernasquicklyasotherlanguages.AmustwatchforeveryJavadeveloper(around1h)
2.AlekseyShipilv:TheBlackMagicof(Java)MethodDispatch
Inrecentyears,theJVMhasseenquiteafewimprovements,includinginvokedynamicthatarrivedinJava7asaprerequisiteforJava8lambdas,aswellasagreattoolforother,moredynamiclanguagesbuiltontopoftheJVM,suchasNashorn(http://blog.jooq.org/2014/06/06/java8fridayjavascriptgoessqlwithnashornandjooq/).
invokedynamicisonlyasmall,highlevelpuzzlepieceintheadvancedtrickeryperformedbytheJVM.Whatreallyhappensunderthehoodwhenyoucallmethods?Howaretheyresolved,optimisedbytheJIT?Alekseysarticlesubtitlerevealswhatthearticleisreallyabout:
EverythingyouwantedtoknowaboutBlackDeviouslySurreptitiousMagicinlowlevelperformanceengineering
Definitelynotasimpleread,butagreatposttolearnaboutthepoweroftheJVM.
ReadAlekseysTheBlackMagicof(Java)MethodDispatch(http://shipilev.net/blog/2015/blackmagicmethoddispatch/)
3.OliverWhite:JavaToolsandTechnologiesLandscapefor2014
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 5/48
Werealreadyin2015,butthisreportbyOliverWhite(atthetimeheadofZeroTurnaroundsRebelLabs(http://zeroturnaround.com/rebellabs/))hadbeenexceptionallywellexecutedandtouchesprettymucheverythingrelatedtotheJavaecosystem.
ReadOliversJavaToolsandTechnologiesLandscapefor2014(http://zeroturnaround.com/rebellabs/javatoolsandtechnologieslandscapefor2014/)
4.PeterLawrey:JavaLambdasandLowLatency
WhenAlekseyhasintroducedustosomeperformancesemanticsintheJVM,Petertakesthisonestepfurther,talkingaboutlowlatencyinJava8.WecouldhavepickedmanyotherusefullittleblogpostsfromPetersblog,whichisallaboutlowlatency,highperformancecomputingontheJVM,sometimesevendoingadvancedoffheaptrickery.
ReadPetersJavaLambdasandLowLatency(http://vanillajava.blogspot.ch/2015/01/javalambdasandlowlatency.html)
5.NicolaiParlog:EverythingYouNeedToKnowAboutDefaultMethods
NicolaiisanewcomerintheJavablogosphere,andaverypromisingone,too.HiswellresearchedarticlesgoindepthaboutsomeinterestingfactsrelatedtoJava8,diggingoutoldemailsfromtheexpertgroupsmailinglist,explainingthedecisionstheymadetoconcludewithwhatwecallJava8today.
ReadNicolaisEverythingYouNeedToKnowAboutDefaultMethods(http://blog.codefx.org/jdk/everythingaboutdefaultmethods/)
6.LukasEder:10ThingsYouDidntKnowAboutJava
ThislistwouldntbecompletewithoutlistinganotherlistthatwewroteourselvesonthejOOQblog.Javaisanoldbeastwith20yearsofhistorythisyearin2015.Thisoldbeasthasalotofsecretsandcaveatsthatmanypeoplehaveforgottenorneverthoughtabout.Weveuncoveredthemforyou:
ReadLukass10ThingsYouDidntKnowAboutJava(http://blog.jooq.org/2014/11/03/10thingsyoudidntknowaboutjava/)
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 6/48
7.EdwinDalorzo:WhyThereIsInterfacePollutioninJava8
Edwinhasbeenrespondingtoourownblogpostsacoupleoftimesinthepastwithverywellresearchedandthoroughlythoughtthrougharticles,inparticularaboutJava8relatedfeatures,e.g.comparingJava8StreamswithLINQ(http://blog.informatech.cr/2013/03/24/javastreamspreviewvsnetlinq/)(somethingthatwevedoneourselves,aswell(http://blog.jooq.org/2013/11/02/doesjava8stillneedlinqorisitbetterthanlinq/)).
ThisparticulararticleexplainswhytherearesomanydifferentanddifferentlynamedfunctionalinterfacesinJava8.
ReadEdwinsWhyThereIsInterfacePollutioninJava8(http://blog.informatech.cr/2014/04/04/jdk8interfacepollution/)
8.VladMihalcea:HowDoesPESSIMISTIC_FORCE_INCREMENTLockModeWork
WhenJavatalkstodatabases,manypeopledefaulttousingHibernateforconvenience(seealso3.OliverWhite:JavaToolsandTechnologiesLandscapefor2014(http://zeroturnaround.com/rebellabs/javatoolsandtechnologieslandscapefor2014/)).Hibernatesmainvision,however,isnottoaddconvenienceyoucangetthatinmanyotherwaysaswell(http://www.hibernatealternative.com/).HibernatesmainvisionistoprovidepowerfulmeansofnavigatingandpersistinganobjectgraphrepresentationofyourRDBMSsdatamodel,includingvariouswaysoflocking.
VladisanextremelyproficientHibernateuser,whohasawholeblogseriesonhowHibernateworksgoing.Wevepickedarecent,wellresearchedarticleaboutlocking,butwestronglysuggestyoureadtheotherarticlesaswell:
ReadVladsHowDoesPESSIMISTIC_FORCE_INCREMENTLockModeWork(http://vladmihalcea.com/2015/02/16/hibernatelockingpatternshowdoespessimistic_force_incrementlockmodework/)
9.PetriKainulainen:WritingCleanTests
ThisisntapurelyJavarelatedblogpost,althoughitiswrittenfromtheperspectiveofaJavadeveloper.Moderndevelopmentinvolvestestingautomatictestingandlotsofit.PetrihaswrittenaninterestingblogseriesaboutwritingcleantestsinJavayoushouldntmisshisarticles!
ReadPetrisWritingCleanTests(http://www.petrikainulainen.net/writingcleantests/)
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 7/48
10.EugenParaschiv:Java8ResourcesCollection
Ifyoudontalreadyhaveatleast9opentabswithinterestingstufftoreadafterthislist,getreadyforabrowsertabexplosion!EugenParaschivwhomaintainsbaeldung.com(http://baeldung.com)hasbeencollectingallsortsofveryinterestingresourcesrelatedtoJava8inasinglelinkcollection.Youshoulddefinitelybookmarkthiscollectionandcheckbackfrequentlyforinterestingchanges:
ReadEugensJava8ResourcesCollection(http://www.baeldung.com/java8)
Manyotherarticles
Thereare,ofcourse,manyotherverygoodarticlesprovidingdeepinsightintousefulJavatricks.Ifyoufindyouveencounteredanarticlethatwouldnicelycomplementthislist,pleaseleavealinkanddescriptioninthecommentssection.Futurereaderswillappreciatetheadditionalinsight.
injava,opensourceLeaveacomment
YakShavingisaGoodWaytoImproveanAPI
YakShaving(uncountable)(http://en.wiktionary.org/wiki/yak_shaving):
1. (idiomatic)Anyapparentlyuselessactivitywhich,byallowingyoutoovercomeintermediatedifficulties,allowsyoutosolvealargerproblem.
2. (idiomatic)Alessusefulactivitydonetoconsciouslyorunconsciouslyprocrastinateaboutalargerbutmoreusefultask.
BothinterpretationsofthetermYakShavingasexplainedbyWiktionary(http://en.wiktionary.org/wiki/yak_shaving)areabsolutelyaccuratedescriptionsofmostrefactoringjobs.TheYakShavinginrefactoringitselfcanbedescribedbythisgifshowingwhathappenswhenyouwanttochangealightbulb:
March9,2015
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 8/48
(http://imgur.com/gallery/t0XHtgJ)
However,whendevelopinganAPI,itsnotsuchabadideatoperformactualYakShaving(onlythefirstinterpretation,ofcourse).Letslookatanexamplewhy,fromthedailyworkmaintainingjOOQ(http://www.jooq.org).
TheTask
ForjOOQ3.6,Iwantedtoimplementaverysimplefeature.Feature#2639:AddstoredprocedureOUTvaluestoDEBUGlogoutput(https://github.com/jOOQ/jOOQ/issues/2639).Thisisnotanimportantfeatureatall,butcertainlyveryusefultoalotofjOOQusers.TheideaisthateverytimeyourunastoredprocedurewithDEBUGloggingactivated,youllgettheOUTparametersloggedalongwiththeprocedurecall.Heresavisualisation:
(https://lukaseder.files.wordpress.com/2015/03/debuglog.png)
Now,theactualimplementationwouldhavebeenveryeasy.Justabout10linesofcodeintheexistingLoggerListener(http://www.jooq.org/javadoc/latest/org/jooq/tools/LoggerListener.html)thatalreadytakescareofloggingalltheotherthings.Buttherewereacoupleofcaveats,whichremindedmeoftheabovelightbulbchanginggif:
Theapparentlyuselessactivities
1. TherewasnowaytoaccesstheRETURN_VALUEmetainformationofajOOQRoutine(http://www.jooq.org/javadoc/latest/org/jooq/Routine.html)
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 9/48
2. TherewasnoeasywaytoaccessRoutineINandOUTvaluesgenerically3. TherewaslifecycleeventthatmodelledthemomentwhenOUTparametersarefetchedinjOOQ4. TherewasnowaytoformatRoutineOUTparametersinaniceway
Doesthisfeelfamiliar?Thereisneedforrefactoring!
Do you know that feeling? When you're implementing a really small change and suddenly, in order to implement it nicely, you have 20 changes?
Lukas Eder @lukaseder
@lukaseder Someone sent this to me to explain it. pic.twitter.com/ZBr06UlAir9:11 AM 2 Mar 2015
Jason Herr @herr_jason
Follow
1 RETWEET 2 FAVORITES
02 Mar
Now,thiswholeimplementationishiddeninjOOQsinternals.Itwouldntmattertoomuchforusers,ifthishadbeenhackedtogetherinonewayoranother.Forinstance,obviouslytheRETURN_VALUEmetainformationcouldbeaccessedthroughinternalrefactorings,thesameistrueforINandOUTvalues.Thereareotherlifecycleeventsthatmighthaveworkedjustaswell,andformattingiseasytoreimplement.
ButthisisapopularAPIthatisusedbymanyuserswhomightprofitfromacleanersolution.Thus,whydontwesimplyrefactorandimplement:
1. AddapublicRoutine.getReturnParameter()method(https://github.com/jOOQ/jOOQ/issues/4107)2. AddpublicRoutine.getValue()andsetValue()methods(https://github.com/jOOQ/jOOQ/issues/3748)3. AddExecuteListener.outStart(ExecuteContext)andoutEnd(ExecuteContext)tocapturefetchingof
RoutineOUTparameters(https://github.com/jOOQ/jOOQ/issues/4108)4. AddRoutine.outRecord()andRoutine.inRecord()toviewaRoutineasaRecord
(https://github.com/jOOQ/jOOQ/issues/4109)
Thethingis:
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 10/48
TheAPIimplementoristhefirstAPIconsumer
ItshardtoforeseewhatAPIusersreallywant.ButifyoureimplementinganAPI(orjustafeature),andyoudiscoverthatsomethingismissing,alwaysconsideraddingthatmissingthingtothepublicAPI.Ifitcouldbeusefultoyourself,internally,itcouldbeevenmoreusefultomanyothers.Thisway,youturnonelittlenicefeatureinto5,amplifyingtheuserlove.
Dontgetmewrong.Thisdoesntmeanthateverylittlepieceoffunctionalityneedstobeexposedpublicly,aucontraire.Butthefactthatsomethingiskeepingyouasthemaintainerfromwritingcleancodemightindicatethatothersimplementthesamehackyworkaroundsasyou.Andtheywontaskyouexplicitlyforit!
Dontbelieveit?Heresanentirelysubjectiveanalysisofuserfeedback:
0.2%Hey,thisisacoolproduct,Iwanttohelptheownermakeitbetter,Illprovideaverydescriptive,constructivefeaturerequestandengageforthenext5weekstohelpimplementit.0.8%Whateverdudes.Makethiswork.Please.1.3%Whateverdudes.Makethiswork.ASAP!4.0%WTFiswrongwithyouguys?Didntyouatleastthinkaboutthisonce??4.7%OK,Imgoingtowritethiscompletelyuninformedrantaboutthisproductnow,whichIhatesomuch.Itmakesmylifecompletelymiserable9.0%Ohwell,thisdoesntwork.Letsgohome,its17:00anyways80.0%Ohwell,thisdidntworkyesterdayalready.Letsgohome.ItsFriday,16:00anyways
Now,mostofthislistwasntmeantentirelyseriously,butyougetthepoint.Theremaybethose0.2%ofusers/customersthatloveyouandthatactivelyengagewithyou.Othersmaystillloveyouoratleastlikeyou,buttheywontengage.Youhavetoguesstimatewhattheyneed.
So.Bottomline:
Ifyouneedit,theyprobablyneedit.StartYakShaving!
injavaLeaveacomment
TheJavaLegacyisConstantlyGrowing
IverecentlystumbleduponaveryinterestingcaveatoftheJDKAPIs,theClass.getConstructors()(http://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getConstructors)method.Itsmethodsignatureisthis:
Constructor[]getConstructors()
March5,2015
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 11/48
TheinterestingthinghereisthatClass.getConstructor(Class...)(http://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getConstructorjava.lang.Class...)returnsaConstructor,withbeingmaintained:
ConstructorgetConstructor(Class...parameterTypes)
Whyisthereadifference,i.e.whydoesntthefirstmethodreturnConstructor[]?
LetsconsidertheJavadoc:
NotethatwhilethismethodreturnsanarrayofConstructorobjects(thatisanarrayofconstructorsfromthisclass),thereturntypeofthismethodisConstructor[]andnotConstructor[]asmightbeexpected.Thislessinformativereturntypeisnecessarysinceafterbeingreturnedfromthismethod,thearraycouldbemodifiedtoholdConstructorobjectsfordifferentclasses,whichwouldviolatethetypeguaranteesofConstructor[].
Thatsatoughone.Historically,hereshowthishappened:
Java1.0/Oak:Arrays
InJava1.0(theimmediatesuccessoroftheOakprogramminglanguage(https://en.wikipedia.org/wiki/Oak_(programming_language))),arrayswerealreadyintroduced.Infact,theyhavebeenintroducedbeforethecollectionsAPI,whichwasintroducedinJava1.2.Arrayssufferfromalltheproblemsthatweknowtoday,includingthembeingcovariant,whichleadstoalotofproblemsatruntime,thatcannotbecheckedatcompiletime:
Object[]objects=newString[1];objects[0]=Integer.valueOf(1);//Ouch
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 12/48
Java1.1:ReflectionAPI
ShortofadecentcollectionsAPI,theonlypossiblereturntypeoftheClass.getConstructors()methodwasConstructor[].Areasonabledecisionatthetime.Ofcourse,youcoulddothesamemistakeasabove:
Object[]objects=String.class.getConstructors();objects[0]=Integer.valueOf(1);//Ouch
butintheadditiontotheabove,youcouldalso,rightfully,writethis:
Constructor[]constructors=String.class.getConstructors();constructors[0]=Object.class.getConstructor();
//Muahahahahahahaha
Java1.2:CollectionsAPI
Javahasbeenbackwardscompatiblefromtheveryearlydays,evenfromOakonwards.TheresaveryinterestingpieceofhistoricresearchaboutsomeofOaksbackwardscompatibilityhavingleakedintoJavatothisdateinthisStackOverflowquestion(http://stackoverflow.com/a/7202659/521799).
WhileitwouldhavebeennaturaltodesignthereflectionAPIusingcollections,now,itwasalreadytoolate.Abettersolutionmightvebeen:
ListgetConstructors()
However,notethatwedidnthavegenericsyet,sothearrayactuallyconveysmoretypeinformationthanthecollection.
Java1.5:Generics
InJava5,thechangefrom
Constructor[]getConstructors()
to
Constructor[]getConstructors()
hasbeenmadeforthereasonsmentionedabove.Now,thealternativeAPIusingacollectionwoulddefinitelyhavebeenbetter:
ListgetConstructors()
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 13/48
Buttheshiphassailed.
Java,theuglywart
Javaisfulloftheselittlecaveats.TheyrealldocumentedintheJavadocs,andoftenonStackOverflow.Justyesterday,wevedocumentedanewcaveatrelatedtocompletelynewAPIinMapandConcurrentHashMap(http://blog.jooq.org/2015/03/04/avoidrecursioninconcurrenthashmapcomputeifabsent/).
Stewardship:theSoberingParts,averygoodtalkaboutallthosecaveatsandhowharditistomaintainthembyBrianGoetzcanbeseenhere:
Thesummaryofthetalk:
(https://www.youtube.com/watch?v=2y5Pv4yN0b0)
Whenlanguagedesignerstalkaboutthelanguagetheyredesigning
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 14/48
injava,sqlLeaveacomment
jOOQEinalternativerWegmitJavaundSQLzuarbeiten
WevepublishedanarticleintheGermanmagazinewww.javaaktuell.de(http://www.ijug.eu/javaaktuell/dasmagazin.html),whichispublishedbytheiJUGe.V.(http://www.ijug.eu/).
Youcanreadanddownloadthearticlefreeofchargefromourblog!(https://lukaseder.files.wordpress.com/2015/03/022015javaaktuelllukasederjooqeinalternativerwegmitjavaundsqlzuarbeiten.pdf)
InJavagibteskeinStandardAPI,dasdieAusdrucksstrkeundMchtigkeitvonSQLdirektuntersttzt.AlleAufmerksamkeitistaufobjektrelationalesMappingundanderehhereAbstraktionslevelgerichtet,beispielsweiseOQL,HQL,JPQL,CriteriaQuery.jOOQisteinduallizenziertesOpenSourceProdukt,dasdieseLckefllt.EsimplementiertSQLalstypsicheredomnenspezifischeSprachedirektinJavaundisteineguteWahlfrJavaApplikationen,indenenSQLundherstellerspezifischeDatenbankfunktionalittwichtigsind.Eszeigt,wieeinemodernedomnenspezifischeSprachedieEntwicklerproduktivittstarkerhhenkann,indemSQLdirektinJavaeingebettetist.
March2,2015
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 15/48
iJUGJavaAktuell[Februar2015]LukasEderjOOQeinalternativerWegmitJavaundSQLzuarbeiten(https://www.slideshare.net/LukasEder1/ijugjavaaktuellfebruar2015lukasederjooqeinalternativerwegmitjavaundsqlzuarbeiten)fromLukasEder(http://www.slideshare.net/LukasEder1)
injava,scalaLeaveacomment
jOOQvs.SlickProsandConsofEachApproach
Everyframeworkintroducesanewcompromise.Acompromisethatisintroducedbecausetheframeworkmakessomeassumptionsabouthowyoudliketointeractwithyoursoftwareinfrastructure.
AnexampleofwherethiscompromisehasstruckusersrecentlyisthediscussionAreSlickqueriesgenerallyisomorphictotheSQLqueries?(https://groups.google.com/d/msg/scalaquery/K2tch9yxx60/QB055F0pn3gJ).And,ofcourse,theansweris:No.WhatappearstobeasimpleSlickquery:
February24,2015
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 16/48
valsalesJoin=salesjoinpurchasersjoinproductsjoinsupplierson{case(((sale,purchaser),product),supplier)=>sale.productId===product.id&&sale.purchaserId===purchaser.id&&product.supplierId===supplier.id}
turnsintoaratherlargemonsterwithtonsofderivedtablesthataretotallyunnecessary,giventheoriginalquery(formattingismine):
selectx2.x3,x4.x5,x2.x6,x2.x7from(selectx8.x9asx10,x8.x11asx12,x8.x13asx14,x8.x15asx7,x8.x16asx17,x8.x18asx3,x8.x19asx20,x21.x22asx23,x21.x24asx25,x21.x26asx6from(selectx27.x28asx9,x27.x29asx11,x27.x30asx13,x27.x31asx15,x32.x33asx16,x32.x34asx18,x32.x35asx19from(selectx36."id"asx28,x36."purchaser_id"asx29,x36."product_id"asx30,x36."total"asx31from"sale"x36)x27innerjoin(selectx37."id"asx33,x37."name"asx34,x37."address"asx35 from"purchaser"x37)x32on1=1)x8innerjoin(
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 17/48
selectx38."id"asx22,x38."supplier_id"asx24,x38."name"asx26from"product"x38)x21on1=1)x2innerjoin(selectx39."id"asx40,x39."name"asx5,x39."address"asx41from"supplier"x39)x4on((x2.x14=x2.x23)and(x2.x12=x2.x17))and(x2.x25=x4.x40)wherex2.x7>=?
ChristopherVogt,aformerSlickmaintainerandstillactivelyinvolvedmemberoftheSlickcommunity,explainstheaboveinthefollowingwords:
ThismeansthatSlickreliesonyourdatabasesqueryoptimizertobeabletoexecutethesqlquerythatSlickproducedefficiently.CurrentlythatisnotalwaysthecaseinMySQL
OneofthemainideasbehindSlick,accordingtoChristopher,is:
SlickisnotaDSLthatallowsyoutobuildexactlyspecifiedSQLstrings.SlicksScalaquerytranslationallowsforreuseandcompositionandusingScalaasthelanguagetowriteyourqueries.Itdoesnotallowyoutopredicttheexactsqlquery,onlythesemanticsandtheroughstructure.
Slickvs.jOOQ
SinceChristopherlateronalsocomparedSlickwithjOOQ,Iallowedmyselftochimeinandtoaddmytwocents:
Fromahighlevel(withoutactualSlickexperience)IdsaythatSlickandjOOQembracecompositionalityequally
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 18/48
Fromahighlevel(withoutactualSlickexperience)IdsaythatSlickandjOOQembracecompositionalityequallywell.Iveseencrazyqueriesofseveral100soflinesof[jOOQ]SQLincustomercode,composedoverseveralmethods.YoucandothatwithbothAPIs.
Ontheotherhand,asChrissaid:SlickhasafocusonScalacollections,jOOQonSQLtables.
Fromaconceptualperspective(=intheory),thisfocusshouldntmatter.Fromatypesafetyperspective,ScalacollectionsareeasiertotypecheckthanSQLtablesandqueriesbecauseSQLasalanguageitselfisratherhardtotypecheckgiventhatthesemanticsofvariousoftheadvancedSQLclausesaltertypeconfigurationsratherimplicitly(e.g.outerjoins,groupingsets,pivotclauses,unions,groupby,etc.).Fromapracticalperspective,SQLitselfisonlyanapproximationoftheoriginalrelationaltheoriesandhasattainedalifeofitsown.Thismayormaynotmattertoyou.
IguessintheenditreallyboilsdowntowhetheryouwanttoreasonaboutScalacollections(queriesarebetterintegrated/moreidiomaticwithyourclientcode)oraboutSQLtables(queriesarebetterintegrated/moreidiomaticwithyourdatabase).
Atthispoint,Idliketoaddanothertwocentstothediscussion.Customersdontbuytheproductthatyoureselling.Theyneverdo.InthecaseofHibernate,customersanduserswerehopingtobeabletoforgetSQLforever.Theoppositeistrue.AsGavinKinghimself(thecreatorofHibernate)hadtoldme:
(https://plus.google.com/+GavinKing/posts/LGJU1NorAvY)
BecausecustomersandusershadneverlistenedtoGavin(andtootherORMcreators),wenowhavewhatmanycalltheobjectrelationalimpedancemismatch(https://en.wikipedia.org/wiki/Objectrelational_impedance_mismatch).AlotofunjustifiedcriticismhasbeenexpressedagainstHibernateandJPA,APIswhicharesimplytoopopularforthelimitedscopetheyreallycover.
WithSlick(orC#sLINQ,forthatmatter(http://blog.jooq.org/2013/11/02/doesjava8stillneedlinqorisitbetterthanlinq/)),asimilarmismatchisimpedingintegrations,ifusersabusethesetoolsforwhattheybelievetobeareplacementforSQL.SlickdoesagreatjobatmodellingtherelationalmodeldirectlyintheScalalanguage.Thisiswonderfulifyouwanttoreasonaboutrelationsjustlikeyoureasonaboutcollections.ButitisnotaSQLAPI.Toillustratehowdifficultitistoovercometheselimitations,youcanbrowsetheissuetrackerorusergrouptolearnabout:
Unwantedderivedtables(https://github.com/slick/slick/issues/623)Limitedsupportforouterjoin(https://groups.google.com/forum/#!topic/scalaquery/Uv9C0QPhYFI)
Wellsimplycallthis:
TheFunctionalRelationalImpedanceMismatch
SQLismuchmore
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 19/48
MarkusWinand(theauthorofthepopularSQLPerformanceExplained(http://sqlperformanceexplained.com/l))hasrecentlypublishedaverygoodpresentationaboutmodernSQL,anideathatwefullyembraceatjOOQ:
ModernSQLinPostgreSQL(https://www.slideshare.net/MarkusWinand/modernsql)fromMarkusWinand(http://www.slideshare.net/MarkusWinand)WebelievethatAPIsthathavebeentryingtohidetheSQLlanguagefromgeneralpurposelanguageslikeJava,Scala,C#aremissingoutonalotoftheverynicefeaturesthatcanaddtremendousvaluetoyourapplication.jOOQisanAPIthatfullyembracestheSQLlanguage,withallitsawesomefeatures(andwithallitsquirks).Youobviouslymayormaynotagreewiththat.
Wellleavethisarticleopenended,hopingyoullchimeintodiscussthebenefitsandcaveatsofeachapproach.OfstayingclosetoScalavs.stayingclosetoSQL.
Asasmallteaser,however,Idliketoannounceafollowuparticleshowingthatthereisnosuchthingasanobjectrelationalimpedancemismatch.You(andyourORM)arejustnotusingSQLcorrectly.Staytuned!
injavaLeaveacomment
ThouShaltNotNameThyMethodEquals
(unlessyoureallyoverrideObject.equals()(http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equalsjava.lang.Object),ofcourse).
IvestumbleduponarathercuriousStackOverflowquestion(http://stackoverflow.com/q/28563304/521799)
February18,2015
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 20/48
IvestumbleduponarathercuriousStackOverflowquestion(http://stackoverflow.com/q/28563304/521799)byuserFrank:
WhydoesJavasArea#equalsmethodnotoverrideObject#equals?
Interestingly,thereisaArea.equals(Area)(http://docs.oracle.com/javase/8/docs/api/java/awt/geom/Area.html#equalsjava.awt.geom.Area)methodwhichreallytakesanAreaargument,insteadofaObjectargumentasdeclaredinObject.equals().Thisleadstorathernastybehaviour,asdiscoveredbyFrank:
@org.junit.TestpublicvoidtestEquals(){java.awt.geom.Areaa=newjava.awt.geom.Area();java.awt.geom.Areab=newjava.awt.geom.Area();assertTrue(a.equals(b));//>true
java.lang.Objecto=b;assertTrue(a.equals(o));//>false}
Technically,itiscorrectforAWTsAreatohavebeenimplementedthisway(ashashCode()isntimplementedeither),butthewayJavaresolvesmethods,andthewayprogrammersdigestcodethathasbeenwrittenliketheabovecode,itisreallyaterribleideatooverloadtheequalsmethod.
Nostaticequals,either
Theserulesalsoholdtrueforstaticequals()methods,suchasforinstanceApacheCommonsLang(http://commons.apache.org/proper/commonslang/)s
ObjectUtils.equals(Objecto1,Objecto2)
Theconfusionherearisesbythefactthatyoucannotstaticimportthisequalsmethod:
importstaticorg.apache.commons.lang.ObjectUtils.equals;
Whenyounowtypethefollowing:
equals(obj1,obj2);
Youwillgetacompilererror:
Themethodequals(Object)inthetypeObjectisnotapplicableforthearguments(,)
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 21/48
Thereasonforthisisthatmethodsthatareinthescopeofthecurrentclassanditssupertypeswillalwaysshadowanythingthatyouimportthisway.Thefollowingdoesntworkeither:
importstaticorg.apache.commons.lang.ObjectUtils.defaultIfNull;
publicclassTest{voidtest(){defaultIfNull(null,null);//^^compilationerrorhere}
voiddefaultIfNull(){}}
DetailsinthisStackOverflowquestion(http://stackoverflow.com/q/7890853/521799).
Conclusion
Theconclusionissimple.neveroverloadanyofthemethodsdeclaredinObject(overridingisfine,ofcourse).Thisincludes:
clone()equals()finalize()getClass()hashCode()notify()notifyAll()toString()wait()
Ofcourse,itwouldbegreatifthosemethodswerentdeclaredinObjectinthefirstplace,butthatshiphassailed20yearsago.
injava,java88Comments
Top10EasyPerformanceOptimisationsinJava
February5,2015
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 22/48
Therehasbeenalotofhypeaboutthebuzzwordwebscale(http://www.mongodbiswebscale.com/),andpeoplearegoingthroughlengthsofreorganisingtheirapplicationarchitecturetogettheirsystemstoscale.
Butwhatisscaling,andhowcanwemakesurethatwecanscale?
Differentaspectsofscaling
Thehypementionedaboveismostlyaboutscalingload,i.e.tomakesurethatasystemthatworksfor1userwillalsoworkwellfor10users,or100users,ormillions.Ideally,yoursystemisasstatelessaspossiblesuchthatthefewpiecesofstatethatreallyremaincanbetransferredandtransformedonanyprocessingunitinyournetwork.Whenloadisyourproblem,latencyisprobablynot,soitsOKifindividualrequeststake50100ms.Thisisoftenalsoreferredtoasscalingout
Anentirelydifferentaspectofscalingisaboutscalingperformance,i.e.tomakesurethatanalgorithmthatworksfor1pieceofinformationwillalsoworkwellfor10pieces,or100pieces,ormillions.WhetherthistypeofscalingisfeasibleisbestdescribedbyBigONotation(http://en.wikipedia.org/wiki/Big_O_notation).Latencyisthekillerwhenscalingperformance.Youwanttodoeverythingpossibletokeepallcalculationonasinglemachine.Thisisoftenalsoreferredtoasscalingup
Iftherewasanythinglikefreelunch(thereisnt(https://en.wikipedia.org/wiki/CAP_theorem)),wecouldindefinitelycombinescalingupandout.Anyway,today,weregoingtolookatsomeveryeasywaystoimprovethingsontheperformanceside.
BigONotation
Java7sForkJoinPool(http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ForkJoinPool.html)aswellasJava8sparallelStream(docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html)helpparallelisingstuff,whichisgreatwhenyoudeployyourJavaprogramontoamulticoreprocessormachine.Theadvantageofsuchparallelismcomparedtoscalingacrossdifferentmachinesonyournetworkisthefactthatyoucanalmostcompletelyeliminatelatencyeffects,asallcorescanaccessthesamememory.
Butdontbefooledbytheeffectthatparallelismhas!Rememberthefollowingtwothings:
Parallelismeatsupyourcores.Thisisgreatforbatchprocessing,butanightmareforasynchronousservers(suchasHTTP).Therearegoodreasonswhyweveusedthesinglethreadservletmodelinthepastdecades.Soparallelismonlyhelpswhenscalingup.ParallelismhasnoeffectonyouralgorithmsBigONotation.IfyouralgorithmisO(nlogn),andyouletthatalgorithmrunonccores,youwillstillhaveanO(nlogn/c)algorithm,ascisaninsignificantconstantinyouralgorithmscomplexity.Youwillsavewallclocktime,butnotreducecomplexity!
Thebestwaytoimproveperformance,ofcourse,isbyreducingalgorithmcomplexity.ThekillerisachieveO(1)orquasiO(1),ofcourse,forinstanceaHashMaplookup.Butthatisnotalwayspossible,letaloneeasy.
Ifyoucannotreduceyourcomplexity,youcanstillgainalotofperformanceifyoutweakyouralgorithm
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 23/48
Ifyoucannotreduceyourcomplexity,youcanstillgainalotofperformanceifyoutweakyouralgorithmwhereitreallymatters,ifyoucanfindtherightspots.Assumethefollowingvisualrepresentationofanalgorithm:
(https://lukaseder.files.wordpress.com/2015/02/algorithm2.png)
TheoverallcomplexityofthealgorithmisO(N ),orO(NxOxP)ifwewanttodealwithindividualordersofmagnitude.However,whenprofilingthiscode,youmightfindafunnyscenario:
Onyourdevelopmentbox,theleftbranch(N>M>Heavyoperation)istheonlybranchthatyoucanseeinyourprofiler,becausethevaluesforOandParesmallinyourdevelopmentsampledata.Onproduction,however,therightbranch(N>O>P>EasyoperationoralsoN.O.P.E.)isreallycausingtrouble.YouroperationsteammighthavefiguredthisoutusingAppDynamics(http://www.appdynamics.com),orDynaTrace(http://www.dynatrace.com),orsomesimilarsoftware.
Withoutproductiondata,youmightquicklyjumptoconclusionsandoptimisetheheavyoperation.Youshiptoproductionandyourfixhasnoeffect.
Therearenogoldenrulestooptimisationapartfromthefactsthat:
AwelldesignedapplicationismucheasiertooptimisePrematureoptimisationwillnotsolveanyperformanceproblems,butmakeyourapplicationlesswelldesigned,whichinturnmakesithardertobeoptimised
Enoughtheory.Letsassumethatyouhavefoundtherightbranchtobetheissue.Itmaywellbethataveryeasyoperationisblowingupinproduction,becauseitiscalledlotsandlotsoftimes(ifN,O,andParelarge).PleasereadthisarticleinthecontextoftherebeingaproblemattheleafnodeofaninevitableO(N )algorithm.Theseoptimisationswonthelpyouscale.Theyllhelpyousaveyourcustomersdayfornow,deferringthedifficultimprovementoftheoverallalgorithmuntillater!
Herearethetop10easyperformanceoptimisationsinJava:
3
3
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 24/48
1.UseStringBuilder
ThisshouldbeyourdefaultinalmostallJavacode.Trytoavoidthe+operator.Sure,youmayarguethatitisjustsyntaxsugarforaStringBuilder(http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)anyway,asin:
Stringx="a"+args.length+"b";
whichcompilesto
0newjava.lang.StringBuilder[16]3dup4ldc[18]6invokespecialjava.lang.StringBuilder(java.lang.String)[20]9aload_0[args]10arraylength11invokevirtualjava.lang.StringBuilder.append(int):java.lang.StringBuilder[23]14ldc[27]16invokevirtualjava.lang.StringBuilder.append(java.lang.String):java.lang.StringBuilder[29]19invokevirtualjava.lang.StringBuilder.toString():java.lang.String[32]22astore_1[x]
Butwhathappens,iflateron,youneedtoamendyourStringwithoptionalparts?
Stringx="a"+args.length+"b";
if(args.length==1)x=x+args[0];
YouwillnowhaveasecondStringBuilder,thatjustneedlesslyconsumesmemoryoffyourheap,puttingpressureonyourGC.Writethisinstead:
StringBuilderx=newStringBuilder("a");x.append(args.length);x.append("b");
if(args.length==1);x.append(args[0]);
Takeaway
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 25/48
Intheaboveexample,itisprobablycompletelyirrelevantifyoureusingexplicitStringBuilderinstances,orifyourelyontheJavacompilercreatingimplicitinstancesforyou.Butremember,wereintheN.O.P.E.branch.EveryCPUcyclethatwerewastingonsomethingasstupidasGCorallocatingaStringBuildersdefaultcapacity,werewastingNxOxPtimes.
Asaruleofthumb,alwaysuseaStringBuilder(http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html)ratherthanthe+operator.Andifyoucan,keeptheStringBuilderreferenceacrossseveralmethods,ifyourStringismorecomplextobuild.ThisiswhatjOOQ(http://www.jooq.org)doeswhenyougenerateacomplexSQLstatement.ThereisonlyoneStringBuilderthattraversesyourwholeSQLAST(AbstractSyntaxTree)(http://en.wikipedia.org/wiki/Abstract_syntax_tree)
Andforcryingoutloud,ifyoustillhaveStringBuffer(http://docs.oracle.com/javase/8/docs/api/java/lang/StringBuffer.html)references,doreplacethembyStringBuilder.Youreallyhardlyeverneedtosynchronizeonastringbeingcreated.
2.Avoidregularexpressions
Regularexpressionsarerelativelycheapandconvenient.ButifyoureintheN.O.P.E.branch,theyreabouttheworstthingyoucando.Ifyouabsolutelymustuseregularexpressionsincomputationintensivecodesections,atleastcachethePattern(http://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html)referenceinsteadofcompilingitafreshallthetime:
staticfinalPatternHEAVY_REGEX=Pattern.compile("(((X)*Y)*Z)*");
Butifyourregularexpressionisreallysillylike
String[]parts=ipAddress.split("\\.");
thenyoureallybetterresorttoordinarychar[]orindexbasedmanipulation.Forexamplethisutterlyunreadableloopdoesthesamething:
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 26/48
intlength=ipAddress.length();intoffset=0;intpart=0;for(inti=0;i
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 27/48
privateclassItrimplementsIterator{intcursor;intlastRet=1;intexpectedModCount=modCount;//...
Instead,youcanwritethefollowing,equivalentloopandwasteonlyasingleintvalueonthestack,whichisdirtcheap:
intsize=strings.size();for(inti=0;i
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 28/48
if(type==Integer.class){result=(T)wasNull(rs,Integer.valueOf(rs.getInt(index)));}
//Andthen...staticfinalTwasNull(ResultSetrs,Tvalue)throwsSQLException{returnrs.wasNull()?null:value;}
ThislogicwillnowcallResultSet.wasNull()everytimeyougetanintfromtheresultset.ButthegetInt()contractreads:
Returns:thecolumnvalue;ifthevalueisSQLNULL,thevaluereturnedis0
Thus,asimple,yetpossiblydrasticimprovementtotheabovewouldbe:
staticfinalTwasNull(ResultSetrs,Tvalue)throwsSQLException{return(value==null||(value.intValue()==0&&rs.wasNull()))?null:value;}
So,thisisanobrainer:
Takeaway
Dontcallexpensivemethodsinanalgorithmsleafnodes,butcachethecallinstead,oravoiditifthemethodcontractallowsit.
5.Useprimitivesandthestack
TheaboveexampleisfromjOOQ(http://www.jooq.org),whichusesalotofgenerics,andthusisforcedtousewrappertypesforbyte,short,int,andlongatleastbeforegenericswillbespecialisableinJava10andprojectValhalla(http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html).Butyoumaynothavethisconstraintinyourcode,soyoushouldtakeallmeasurestoreplace:
//GoestotheheapIntegeri=817598;
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 29/48
bythis:
//Staysonthestackinti=817598;
Thingsgetworsewhenyoureusingarrays:
//Threeheapobjects!Integer[]i={1337,424242};
bythis:
//Oneheapobject.int[]i={1337,424242};
Takeaway
WhenyouredeepdowninyourN.O.P.E.branch,youshouldbeextremelywaryofusingwrappertypes.ChancesarethatyouwillcreatealotofpressureonyourGC,whichhastokickinallthetimetocleanupyourmess.
Aparticularlyusefuloptimisationmightbetousesomeprimitivetypeandcreatelarge,onedimensionalarraysofit,andacoupleofdelimitervariablestoindicatewhereexactlyyourencodedobjectislocatedonthearray.
Anexcellentlibraryforprimitivecollections,whichareabitmoresophisticatedthanyouraverageint[]istrove4j(http://trove4j.sourceforge.net),whichshipswithLGPL.
Exception
Thereisanexceptiontothisrule:booleanandbytehavefewenoughvaluestobecachedentirelybytheJDK.Youcanwrite:
Booleana1=true;//...syntaxsugarfor:Booleana2=Boolean.valueOf(true);
Byteb1=(byte)123;//...syntaxsugarfor:Byteb2=Byte.valueOf((byte)123);
Thesameistrueforlowvaluesoftheotherintegerprimitivetypes,includingchar,short,int,long.
Butonlyifyoureautoboxingthem,orcallingTheType.valueOf(),notwhenyoucalltheconstructor!
Nevercalltheconstructoronwrappertypes,unlessyoureallywantanewinstance
Thisfactcanalsohelpyouwriteasophisticated,trollingAprilFoolsjokeforyourcoworkers(http://blog.jooq.org/2013/10/17/addsomeentropytoyourjvm/)
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 30/48
Offheap
Ofcourse,youmightalsowanttoexperimentwithoffheaplibraries,althoughtheyremoreofastrategicdecision,notalocaloptimisation.
AninterestingarticleonthatsubjectbyPeterLawreyandBenCottonis:OpenJDKandHashMapSafelyTeachinganOldDogNew(OffHeap!)Tricks(http://www.infoq.com/articles/OpenJDKandHashMapOffHeap)
6.Avoidrecursion
ModernfunctionalprogramminglanguageslikeScalaencouragetheuseofrecursion,astheyoffermeansofoptimisingtailrecursingalgorithmsbackintoiterativeones(http://stackoverflow.com/q/33923/521799).Ifyourlanguagesupportssuchoptimisations,youmightbefine.Buteventhen,theslightestchangeofalgorithmmightproduceabranchthatpreventsyourrecursionfrombeingtailrecursive.Hopefullythecompilerwilldetectthis!Otherwise,youmightbewastingalotofstackframesforsomethingthatmighthavebeenimplementedusingonlyafewlocalvariables.
Takeaway
Theresnotmuchtosayaboutthisapartfrom:AlwayspreferiterationoverrecursionwhenyouredeepdowntheN.O.P.E.branch
7.UseentrySet()
WhenyouwanttoiteratethroughaMap(https://docs.oracle.com/javase/8/docs/api/java/util/Map.html),andyouneedbothkeysandvalues,youmusthaveaverygoodreasontowritethefollowing:
for(Kkey:map.keySet()){Vvalue:map.get(key);}
ratherthanthefollowing:
for(Entryentry:map.entrySet()){Kkey=entry.getKey();Vvalue=entry.getValue();}
WhenyoureintheN.O.P.E.branch,youshouldbewaryofmapsanyway,becauselotsandlotsofO(1)map
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 31/48
WhenyoureintheN.O.P.E.branch,youshouldbewaryofmapsanyway,becauselotsandlotsofO(1)mapaccessoperationsarestilllotsofoperations.Andtheaccessisntfreeeither.Butatleast,ifyoucannotdowithoutmaps,useentrySet()(https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#entrySet)toiteratethem!TheMap.Entryinstanceisthereanyway,youonlyneedtoaccessit.
Takeaway
AlwaysuseentrySet()whenyouneedbothkeysandvaluesduringmapiteration.
8.UseEnumSetorEnumMap
Therearesomecaseswherethenumberofpossiblekeysinamapisknowninadvanceforinstancewhenusingaconfigurationmap.Ifthatnumberisrelativelysmall,youshouldreallyconsiderusingEnumSetorEnumMap,insteadofregularHashSetorHashMapinstead.ThisiseasilyexplainedbylookingatEnumMap.put():
privatetransientObject[]vals;
publicVput(Kkey,Vvalue){//...intindex=key.ordinal();vals[index]=maskNull(value);//...}
Theessenceofthisimplementationisthefactthatwehaveanarrayofindexedvaluesratherthanahashtable.Wheninsertinganewvalue,allwehavetodotolookupthemapentryisasktheenumforitsconstantordinal,whichisgeneratedbytheJavacompileroneachenumtype.Ifthisisaglobalconfigurationmap(i.e.onlyoneinstance),theincreasedaccessspeedwillhelpEnumMapheavilyoutperformHashMap,whichmayuseabitlessheapmemory,butwhichwillhavetorunhashCode()andequals()oneachkey.
Takeaway
EnumandEnumMapareveryclosefriends.Wheneveryouuseenumlikestructuresaskeys,consideractuallymakingthosestructuresenumsandusingthemaskeysinEnumMap.
9.OptimiseyourhashCode()andequals()methods
IfyoucannotuseanEnumMap,atleastoptimiseyourhashCode()andequals()methods.AgoodhashCode()methodisessentialbecauseitwillpreventfurthercallstothemuchmoreexpensiveequals()asitwillproducemoredistincthashbucketspersetofinstances.
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 32/48
Ineveryclasshierarchy,youmayhavepopularandsimpleobjects.LetshavealookatjOOQsorg.jooq.Table(http://www.jooq.org/javadoc/latest/org/jooq/Table.html)implementations.
ThesimplestandfastestpossibleimplementationofhashCode()isthisone:
//AbstractTable,acommonTablebaseimplementation:
@OverridepublicinthashCode(){
//[#1938]ThisisamuchmoreefficienthashCode()//implementationcomparedtothatofstandard//QueryPartsreturnname.hashCode();}
wherenameissimplythetablename.Wedontevenconsidertheschemaoranyotherpropertyofthetable,asthetablenamesareusuallydistinctenoughacrossadatabase.Also,thenameisastring,soithasalreadyacachedhashCode()valueinside.
Thecommentisimportant,becauseAbstractTableextendsAbstractQueryPart,whichisacommonbaseimplementationforanyAST(AbstractSyntaxTree)(https://en.wikipedia.org/wiki/Abstract_syntax_tree)element.ThecommonASTelementdoesnothaveanyproperties,soitcannotmakeanyassumptionsanoptimisedhashCode()implementation.Thus,theoverriddenmethodlookslikethis:
//AbstractQueryPart,acommonASTelement//baseimplementation:
@OverridepublicinthashCode(){//Thisisaworkingdefaultimplementation.//Itshouldbeoverriddenbyconcretesubclasses,//toimproveperformancereturncreate().renderInlined(this).hashCode();}
Inotherwords,thewholeSQLrenderingworkflowhastobetriggeredtocalculatethehashcodeofacommonASTelement.
Thingsgetmoreinterestingwithequals()
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 33/48
//AbstractTable,acommonTablebaseimplementation:
@Overridepublicbooleanequals(Objectthat){if(this==that){returntrue;}
//[#2144]Nonequalitycanbedecidedearly,//withoutexecutingtheratherexpensive//implementationofAbstractQueryPart.equals()if(thatinstanceofAbstractTable){if(StringUtils.equals(name,(((AbstractTable)that).name))){returnsuper.equals(that);}
returnfalse;}
returnfalse;}
Firstthing:Always(notonlyinaN.O.P.E.branch)aborteveryequals()methodearly,if:
this==argumentthis"incompatibletype"argument
Notethatthelatterconditionincludesargument==null,ifyoureusinginstanceoftocheckforcompatibletypes.Wevebloggedaboutthisbeforein10SubtleBestPracticeswhenCodingJava(http://blog.jooq.org/2013/08/20/10subtlebestpracticeswhencodingjava/).
Now,afterabortingcomparisonearlyinobviouscases,youmightalsowanttoabortcomparisonearlywhenyoucanmakepartialdecisions.Forinstance,thecontractofjOOQsTable.equals()isthatfortwotablestobeconsideredequal,theymustbeofthesamename,regardlessoftheconcreteimplementationtype.Forinstance,thereisnowaythesetwoitemscanbeequal:
com.example.generated.Tables.MY_TABLEDSL.tableByName("MY_OTHER_TABLE")
Iftheargumentcannotbeequaltothis,andifwecancheckthateasily,letsdosoandabortifthecheckfails.Ifthechecksucceeds,wecanstillproceedwiththemoreexpensiveimplementationfromsuper.Giventhatmostobjectsintheuniversearenotequal,weregoingtosavealotofCPUtimebyshortcuttingthismethod.
someobjectsaremoreequalthanothers
InthecaseofjOOQ,mostinstancesarereallytablesasgeneratedbythejOOQsourcecodegenerator(http://www.jooq.org/doc/3.5/manual/codegeneration/),whoseequals()implementationisevenfurtheroptimised.Thedozensofothertabletypes(derivedtables,tablevaluedfunctions,arraytables,joinedtables,
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 34/48
pivottables,commontableexpressions,etc.)cankeeptheirsimpleimplementation.
10.Thinkinsets,notinindividualelements
Lastbutnotleast,thereisathingthatisnotJavarelatedbutappliestoanylanguage.Besides,wereleavingtheN.O.P.E.branchasthisadvicemightjusthelpyoumovefromO(N )toO(nlogn),orsomethinglikethat.
Unfortunately,manyprogrammersthinkintermsofsimple,localalgorithms.Theyresolvingaproblemstepbystep,branchbybranch,loopbyloop,methodbymethod.Thatstheimperativeand/orfunctionalprogrammingstyle.Whileitisincreasinglyeasytomodelthebiggerpicturewhengoingfrompureimperativetoobjectoriented(stillimperative)tofunctionalprogramming,allthesestyleslacksomethingthatonlySQLandRandsimilarlanguageshave:
Declarativeprogramming.
InSQL(andweloveit,asthisisthejOOQblog(http://blog.jooq.org))youcandeclaretheoutcomeyouwanttogetfromyourdatabase,withoutmakinganyalgorithmicimplicationswhatsoever.Thedatabasecanthentakeallthemetadataavailableintoconsideration(e.g.constraints,keys,indexes,etc.(http://blog.jooq.org/2011/11/25/howschemametadataimpactsoraclequerytransformations/))tofigureoutthebestpossiblealgorithm.
Intheory,thishasbeenthemainideabehindSQLandrelationalcalculus(https://en.wikipedia.org/wiki/Relational_calculus)fromthebeginning.Inpractice,SQLvendorshaveimplementedhighlyefficientCBOs(CostBasedOptimisers)(https://www.youtube.com/watch?v=CjY8TCU69TU)onlysincethelastdecade,sostaywithusinthe2010swhenSQLwillfinallyunleashitsfullpotential(itwasabouttime!)
ButyoudonthavetodoSQLtothinkinsets.Sets/collections/bags/listsareavailableinalllanguagesandlibraries.Themainadvantageofusingsetsisthefactthatyouralgorithmswillbecomemuchmuchmoreconcise.Itissomucheasiertowrite:
SomeSetINTERSECTSomeOtherSet
ratherthan:
//PreJava8Setresult=newHashSet();for(Objectcandidate:someSet)if(someOtherSet.contains(candidate))result.add(candidate);
//EvenJava8doesn'treallyhelpsomeSet.stream().filter(someOtherSet::contains).collect(Collectors.toSet());
3
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 35/48
SomemayarguethatfunctionalprogrammingandJava8willhelpyouwriteeasier,moreconcisealgorithms.Thatsnotnecessarilytrue.YoucantranslateyourimperativeJava7loopintoafunctionalJava8Streamcollection,butyourestillwritingtheverysamealgorithm.WritingaSQLesqueexpressionisdifferent.This
SomeSetINTERSECTSomeOtherSet
canbeimplementedin1000waysbytheimplementationengine.Aswevelearnedtoday,perhapsitiswisetotransformthetwosetsintoEnumSetautomatically,beforerunningtheINTERSECToperation.PerhapswecanparallelisethisINTERSECTwithoutmakinglowlevelcallstoStream.parallel()(https://docs.oracle.com/javase/8/docs/api/java/util/stream/BaseStream.html#parallel)
Conclusion
Inthisarticle,wevetalkedaboutoptimisationsdoneontheN.O.P.E.branch,i.e.deepdowninahighcomplexityalgorithm.Inourcase,beingthejOOQ(http://www.jooq.org)developers,wehaveinterestinoptimisingourSQLgeneration:
EveryqueryisgeneratedonlyonasingleStringBuilderOurtemplatingengineactuallyparsescharacters,insteadofusingregularexpressionsWeusearrayswhereverwecan,especiallywheniteratingoverlistenersWestayclearofJDBCmethodsthatwedonthavetocalletc
jOOQisatthebottomofthefoodchain,becauseitsthe(second)lastAPIthatisbeingcalledbyourcustomersapplicationsbeforethecallleavestheJVMtoentertheDBMS.BeingatthebottomofthefoodchainmeansthateverylineofcodethatisexecutedinjOOQmightbecalledNxOxPtimes,sowemustoptimiseeagerly.
YourbusinesslogicisnotdeepdownintheN.O.P.E.branch.Butyourown,homegrowninfrastructurelogicmaybe(customSQLframeworks,customlibraries,etc.)Thoseshouldbereviewedaccordingtotherulesthatweveseentoday.Forinstance,usingJavaMissionControl(http://blog.jooq.org/2014/02/17/freejavaprofilingwithoraclejavamissioncontrol/)oranyotherprofiler.
Likedthisarticle?
Ifyoucantgoandprofileyourapplicationrightnow,youmightenjoyreadinganyofthesearticlesinstead:
10SubtleMistakesWhenUsingtheStreamsAPI(http://blog.jooq.org/2014/06/13/java8friday10subtlemistakeswhenusingthestreamsapi/)10ThingsYouDidntKnowAboutJava(http://blog.jooq.org/2014/11/03/10thingsyoudidntknowaboutjava/)10SubtleBestPracticeswhenCodingJava(http://blog.jooq.org/2013/08/20/10subtlebestpracticeswhencodingjava/)
injavaFebruary2,2015
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 36/48
4Comments
Top5UseCasesForNestedTypes
Therehasbeenaninterestingdiscussiononreddit,theotherdayStaticInnerClasses.Whenisittoomuch?(http://redd.it/2u4512)
First,letsreviewalittlebitofbasichistoricJavaknowledge.Javathelanguageoffersfourlevelsofnestingclasses(http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html),andbyJavathelanguage,Imeanthattheseconstructsaremeresyntaxsugar.TheydontexistintheJVM,whichonlyknowsordinaryclasses.
(Static)Nestedclasses
classOuter{staticclassInner{}}
Inthiscase,InneriscompletelyindependentofOuter,exceptforacommon,sharednamespace.
Innerclasses
classOuter{classInner{}}
Inthiscase,InnerinstanceshaveanimplicitreferencetotheirenclosingOuterinstance.Inotherwords,therecanbenoInnerinstancewithoutanassociatedOuterinstance.
TheJavawayofcreatingsuchaninstanceisthis:
Outer.Inneryikes=newOuter().newInner();
Whatlookstotallyawkwardmakesalotofsense.ThinkaboutcreatinganInnerinstancesomewhereinsideofOuter:
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 37/48
classOuter{classInner{}
voidsomewhereInside(){//We'realreadyinthescopeofOuter.//Wedon'thavetoqualifyInnerexplicitly.InneraaahOK;
//Thisiswhatwe'reusedtowriting.aaahOK=newInner();
//Asallotherlocallyscopedmethods,wecan//accesstheInnerconstructorby//dereferencingitfrom"this".Wejust//hardlyeverwrite"this"aaahOK=this.newInner();}}
Notethatmuchlikethepublicorabstractkeywords,thestatickeywordisimplicitfornestedinterfaces.Whilethefollowinghypotheticalsyntaxmightlookfamiliaratfirstsight:
classOuter{interfaceInner{defaultvoiddoSomething(){Outer.this.doSomething();}}
voiddoSomething(){}}
itisnotpossibletowritetheabove.Apartfromthelackofakeyword,theredontseemtobeanyobviousreasonwhyinnerinterfacesshouldntbepossible.Idsuspecttheusualtheremustbesomereallyedgecaseycaveatrelatedtobackwardscompatibilityand/ormultipleinheritancethatpreventsthis.
Localclasses
classOuter{voidsomewhereInside(){classInner{}}}
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 38/48
LocalclassesareprobablyoneoftheleastknownfeaturesinJava,asthereishardlyanyuseforthem.Localclassesarenamedtypeswhosescopeextendsonlytotheenclosingmethod.Obvioususecasesarewhenyouwanttoreusesuchatypeseveraltimeswithinthatmethod,e.g.toconstructseveralsimilarlistenersinaJavaFXapplication.
Anonymousclasses
classOuter{Serializabledummy=newSerializable(){};}
Anonymousclassesaresubtypesofanothertypewithonlyonesingleinstance.
Top5UseCasesForNestedClasses
Allofanonymous,local,andinnerclasseskeepareferencetotheirenclosinginstance,iftheyrenotdefinedinastaticcontext.Thismaycausealotoftroubleifyouletinstancesoftheseclassesleakoutsideoftheirscope.Readmoreaboutthattroubleinourarticle:DontbeClever:TheDoubleCurlyBracesAntiPattern(http://blog.jooq.org/2014/12/08/dontbecleverthedoublecurlybracesantipattern/).
Often,however,youdowanttoprofitfromthatenclosinginstance.Itcanbequiteusefultohavesomesortofmessageobjectthatyoucanreturnwithoutdisclosingtheactualimplementation:
classOuter{
//Thisimplementationisprivate...privateclassInnerimplementsMessage{@OverridepublicvoidgetMessage(){Outer.this.someoneCalledMe();}}
//...butwecanreturnit,beingof//typeMessageMessagehello(){returnnewInner();}
voidsomeoneCalledMe(){}}
With(static)nestedclasses,however,thereisnoenclosingscopeastheInnerinstanceiscompletelyindependentofanyOuterinstance.Sowhatsthepointofusingsuchanestedclass,ratherthanatopleveltype?
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 39/48
1.Associationwiththeoutertype
Ifyouwanttocommunicatetothewholeworld,hey,this(inner)typeistotallyrelatedtothis(outer)type,anddoesntmakesenseonitsown,thenyoucannestthetypes.ThishasbeendonewithMapandMap.Entry,forinstance:
publicinterfaceMap{interfaceEntry{}}
2.Hidingfromtheoutsideoftheoutertype
Ifpackage(default)visibilityisntenoughforyourtypesyoucancreateprivatestaticclassesthatareavailableonlytotheirenclosingtypeandtoallothernestedtypesoftheenclosingtype.Thisisreallythemainusecaseforstaticnestedclasses.
classOuter{privatestaticclassInner{}}
classOuter2{Outer.Innernope;}
3.Protectedtypes
Thisisreallyaveryrareusecase,butsometimes,withinaclasshierarchy,youneedtypesthatyouwanttomakeavailableonlytosubtypesofagiventype.Thisisausecaseforprotectedstaticclasses:
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 40/48
classParent{protectedstaticclassOnlySubtypesCanSeeMe{}
protectedOnlySubtypesCanSeeMesomeMethod(){returnnewOnlySubtypesCanSeeMe();}}
classChildextendsParent{OnlySubtypesCanSeeMewow=someMethod();}
4.Toemulatemodules
UnlikeCeylon,Javadoesnthavefirstclassmodules(http://blog.jooq.org/2013/12/03/top10ceylonlanguagefeaturesiwishwehadinjava/).WithMavenorOSGi,itispossibletoaddsomemodularbehaviourtoJavasbuild(Maven)orruntime(OSGi)environments,butifyouwanttoexpressmodulesincode,thisisntreallypossible.
However,youcanestablishmodulesbyconventionbyusingstaticnestedclasses.Letslookatthejava.util.stream(http://docs.oracle.com/javase/8/docs/api/java/util/stream/packagesummary.html)package.Wecouldconsideritamodule,andwithinthismodule,wehaveacoupleofsubmodules,orgroupsoftypes,suchastheinternaljava.util.stream.Nodesclass,whichroughlylookslikethis:
finalclassNodes{privateNodes(){}privatestaticabstractclassAbstractConcNode{}staticfinalclassConcNode{staticfinalclassOfInt{}staticfinalclassOfLong{}}privatestaticfinalclassFixedNodeBuilder{}//...}
SomeofthisNodesstuffisavailabletoallofthejava.util.streampackage,sowemightsaythatthewaythisiswritten,wehavesomethinglike:
asyntheticjava.util.stream.nodessubpackage,visibleonlytothejava.util.streammoduleacoupleofjava.util.stream.nodes.*types,visiblealsoonlytothejava.util.streammoduleacoupleoftoplevelfunctions(staticmethods)inthesyntheticjava.util.stream.nodespackage
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 41/48
LooksalotlikeCeylon,tome!(http://blog.jooq.org/2013/12/03/top10ceylonlanguagefeaturesiwishwehadinjava/)
5.Cosmeticreasons
Thelastbitisratherboring.Orsomemayfinditinteresting(http://blog.jooq.org/2014/07/25/top10veryveryveryimportanttopicstodiscuss/).Itsabouttaste,oreaseofwritingthings.Someclassesarejustsosmallandunimportant,itsjusteasiertowritetheminsideofanotherclass.Savesyoua.javafile.Whynot.
Conclusion
IntimesofJava8,thinkingabouttheveryoldfeaturesofJavathelanguagemightnotprovetobeextremelyexciting.Staticnestedclassesareawellunderstoodtoolforacoupleofnicheusecases.
Thetakeawayfromthisarticle,however,isthis.Everytimeyounestaclass,besuretomakeitstaticifyoudontabsolutelyneedareferencetotheenclosinginstance.Youneverknowwhenthatreferenceisblowingupyourapplicationinproduction(http://blog.jooq.org/2014/12/08/dontbecleverthedoublecurlybracesantipattern/).
injava,java84Comments
YouWillRegretApplyingOverloadingwithLambdas!
WritinggoodAPIsishard.Extremelyhard.YouhavetothinkofanincredibleamountofthingsifyouwantyouruserstoloveyourAPI.Youhavetofindtherightbalancebetween:
1. Usefulness2. Usability3. Backwardcompatibility4. Forwardcompatibility
Wevebloggedaboutthistopicbefore,inourarticle:HowtoDesignaGood,RegularAPI(http://blog.jooq.org/2013/03/30/howtodesignagoodregularapi/).Today,weregoingtolookintohow
January29,2015
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 42/48
Java8changestherules
Yes!
Overloadingisanicetooltoprovidecovenienceintwodimensions:
ByprovidingargumenttypealternativesByprovidingargumentdefaultvalues
ExamplesfortheabovefromtheJDKinclude:
publicclassArrays{
//Argumenttypealternativespublicstaticvoidsort(int[]a){...}publicstaticvoidsort(long[]a){...}
//ArgumentdefaultvaluespublicstaticIntStreamstream(int[]array){...}publicstaticIntStreamstream(int[]array,intstartInclusive,intendExclusive){...}}
ThejOOQAPIisobviouslyfullofsuchconvenience.AsjOOQisaDSLforSQL(http://www.jooq.org),we
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 43/48
ThejOOQAPIisobviouslyfullofsuchconvenience.AsjOOQisaDSLforSQL(http://www.jooq.org),wemightevenabusealittlebit:
publicinterfaceDSLContext{SelectSelectStepselect(SelectFieldfield1);
SelectSelectStepselect(SelectFieldfield1,SelectFieldfield2);
SelectSelectStepsselect(SelectFieldfield1,SelectFieldfield2,SelectFieldfield3);
SelectSelectStepselect(SelectFieldfield1,SelectFieldfield2,SelectFieldfield3,SelectFieldfield4);
//andsoon...}
LanguageslikeCeylontakethisideaofconvenienceonestepfurtherbyclaimingthattheaboveistheonlyreasonablereasonwhyoverloadingisbeusedinJava.Andthus,thecreatorsofCeylonhavecompletelyremovedoverloadingfromtheirlanguage,replacingtheabovebyuniontypesandactualdefaultvaluesforarguments.E.g.
//Uniontypesvoidsort(int[]|long[]a){...}
//DefaultargumentvaluesIntStreamstream(int[]array,intstartInclusive=0,intendInclusive=array.length){...}
ReadTop10CeylonLanguageFeaturesIWishWeHadInJava(http://blog.jooq.org/2013/12/03/top10ceylonlanguagefeaturesiwishwehadinjava/)formoreinformationaboutCeylon.
InJava,unfortunately,wecannotuseuniontypesorargumentdefaultvalues.SowehavetouseoverloadingtoprovideourAPIconsumerswithconveniencemethods.
Ifyourmethodargumentisafunctionalinterface(http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html),however,thingschangeddrasticallybetweenJava7andJava8,withrespecttomethodoverloading.AnexampleisgivenherefromJavaFX.
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 44/48
JavaFXsunfriendlyObservableList
JavaFXenhancestheJDKcollectiontypesbymakingthemobservable.NottobeconfusedwithObservable(http://docs.oracle.com/javase/8/docs/api/java/util/Observable.html),adinosaurtypefromtheJDK1.0andfrompreSwingdays.
JavaFXsownObservable(http://docs.oracle.com/javafx/2/api/javafx/beans/Observable.html)essentiallylookslikethis:
publicinterfaceObservable{voidaddListener(InvalidationListenerlistener);voidremoveListener(InvalidationListenerlistener);}
Andluckily,thisInvalidationListener(http://docs.oracle.com/javafx/2/api/javafx/beans/InvalidationListener.html)isafunctionalinterface:
@FunctionalInterfacepublicinterfaceInvalidationListener{voidinvalidated(Observableobservable);}
Thisisgreat,becausewecandothingslike:
Observableawesome=FXCollections.observableArrayList();awesome.addListener(fantastic>splendid.cheer());
(noticehowIvereplacedfoo/bar/bazwithmorecheerfulterms.Weshouldalldothat.Fooandbarareso1970(http://en.wikipedia.org/wiki/Foobar))
Unfortunately,thingsgetmorehairywhenwedowhatwewouldprobablydo,instead.I.e.insteadofdeclaringanObservable,wedlikethattobeamuchmoreusefulObservableList(http://docs.oracle.com/javafx/2/api/javafx/collections/ObservableList.html):
ObservableListawesome=FXCollections.observableArrayList();awesome.addListener(fantastic>splendid.cheer());
Butnow,wegetacompilationerroronthesecondline:
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 45/48
awesome.addListener(fantastic>splendid.cheer());//^^^^^^^^^^^//ThemethodaddListener(ListChangeListener
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 46/48
Allofthesemeasureswillremoveambiguity.Butfrankly,lambdasareonlyhalfascoolifyouhavetoexplicitlytypethelambda,ortheargumenttypes.WehavemodernIDEsthatcanperformautocompletionandhelpinfertypesjustasmuchasthecompileritself.
ImagineifwereallywantedtocalltheotheraddListener()method,theonethattakesaListChangeListener.Wedhavetowriteanyof
ObservableListawesome=FXCollections.observableArrayList();
//Agh.Rememberthatwehavetorepeat"String"hereListChangeListenerhearYe=fantastic>splendid.cheer();awesome.addListener(hearYe);
Or
ObservableListawesome=FXCollections.observableArrayList();
//Agh.Rememberthatwehavetorepeat"String"hereawesome.addListener((ListChangeListener)fantastic>splendid.cheer());
Oreven
ObservableListawesome=FXCollections.observableArrayList();
//WTF..."extends"String??Butthat'swhatthisthingneeds...awesome.addListener((Change
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 47/48
takethesamenumberofmethodarguments(asinourpreviousaddListener()example)?
Zero.
Thereareoverloadswhereoverloadargumentnumbersdiffer.Forinstance:
Rcollect(Suppliersupplier,BiConsumeraccumulator,BiConsumercombiner);
Rcollect(Collector
3/24/2015 java|Java,SQLandjOOQ.
http://blog.jooq.org/category/java/ 48/48
BuildawebsitewithWordPress.com