Preface
TheSpringDataMongoDBprojectappliescoreSpringconceptstothedevelopmentofsolutionsusingtheMongoDBdocumentstyledatastore.Weprovidea"template"asahigh-levelabstractionforstoringandqueryingdocuments.YouwillnoticesimilaritiestotheJDBCsupportintheSpringFramework.
PartI.Introduction
ThisdocumentisthereferenceguideforSpringData-DocumentSupport.ItexplainsDocumentmoduleconceptsandsemanticsandthesyntaxforvariousstoresnamespaces.
ThissectionprovidessomebasicintroductiontoSpringandDocumentdatabase.TherestofthedocumentrefersonlytoSpringDataDocumentfeaturesandassumestheuserisfamiliarwithdocumentdatabasessuchasMongoDBandCouchDBaswellasSpringconcepts.
1.KnowingSpring
SpringDatausesSpringframework's
corefunctionality,suchastheIoCcontainer,typeconversionsystem,expressionlanguage,JMXintegration,andportableDAOexceptionhierarchy.WhileitisnotimportanttoknowtheSpringAPIs,understandingtheconceptsbehindthemis.Ataminimum,theideabehindIoCshouldbefamiliarforwhateverIoCcontaineryouchoosetouse.
ThecorefunctionalityoftheMongoDBandCouchDBsupportcanbeuseddirectly,withnoneedtoinvoketheIoCservicesoftheSpringContainer.ThisismuchlikeJdbcTemplatewhichcanbeused'standalone'withoutanyotherservicesoftheSpringcontainer.ToleverageallthefeaturesofSpringDatadocument,suchastherepositorysupport,youwillneedtoconfiguresomepartsofthelibraryusingSpring.
TolearnmoreaboutSpring,youcanrefertothecomprehensive(andsometimesdisarming)documentationthatexplainsindetailtheSpringFramework.Therearealotofarticles,blogentriesandbooksonthematter-takealookattheSpringframeworkhomepageformoreinformation.
2.KnowingNoSQLandDocumentdatabases
NoSQLstoreshavetakenthestorageworldbystorm.Itisavastdomainwithaplethoraofsolutions,termsandpatterns(tomakethingswortheventhetermitselfhasmultiplemeanings).Whilesomeoftheprinciplesarecommon,itiscrucialthattheuserisfamiliartosomedegreewiththestoressupportedbyDATADOC.Thebestwaytogetacquaintedtothissolutionsistoreadtheirdocumentationandfollowtheirexamples-itusuallydoesn'ttakemorethen5-10minutestogothroughthemandifyouarecomingfromanRDMBS-onlybackgroundmanytimestheseexercisescanbeaneyeopener.
ThejumpingoffgroundforlearningaboutMongoDBiswww.mongodb.org.Hereisalistofotherusefulresources.
TheonlineshellprovidesaconvenientwaytointeractwithaMongoDBinstanceincombinationwiththeonlinetutorial.
MongoDBJavaLanguageCenter
Severalbooksavailableforpurchase
KarlSeguin'sonlinebook:"TheLittleMongoDBBook"
Chapter1.WhySpringData-Document?
TheSpringFrameworkistheleadingfull-stackJava/JEEapplicationframework.Itprovidesalightweightcontainerandanon-invasiveprogrammingmodelenabledbytheuseofdependencyinjection,AOP,andportableserviceabstractions.
NoSQLstoragesprovideanalternativetoclassicalRDBMSforhorizontalscalabilityandspeed.Intermsofimplementation,DocumentstoresrepresentoneofthemostpopulartypesofstoresintheNoSQLspace.ThedocumentdatabasesupportedbySpringDataareMongoDBandCouchDB,thoughjustMongoDBintegrationhasbeenreleasedtodate.
ThegoaloftheSpringDataDocument(orDATADOC)frameworkistoprovideanextensiontotheSpringprogrammingmodelthatsupportswritingapplicationsthatuseDocumentdatabases.TheSpringframeworkhasalwayspromotedaPOJOprogrammingmodelwithastrongemphasisonportabilityandproductivity.ThesevaluesarecariedoverintoSpringDataDocument.
NotablefeaturesthatareusedinSpringDataDocumentfromtheSpringframeworkaretheFeaturesthatparticular,featuresfromtheSpringframeworkthatareusedaretheConversionService,JMXExporters,portableDataAccessExceptionhierarchy,SpringExpressionLanguage,andJavabasedIoCcontainerconfiguration.TheprogrammingmodelfollowsthefamiliarSpring'template'style,soifyouarefamilarwithSpringtemplateclassessuchasJdbcTemplate,JmsTemplate,RestTemplate,youwillfeelrightathome.Forexample,MongoTemplateremovesmuchoftheboilerplatecodeyouwouldhavetowritewhenusingtheMongoDBdrivertosavePOJOsaswellasarichjavabasedqueryinterfacetoretrievePOJOs.TheprogrammingmodelalsooffersanewRepositoryapproachinwhichtheSpringcontainerwillprovideanimplementationofaRepositorybasedsoleyoffaninterfacedefinitionwhichcanalsoincludecustomfindermethods.
Chapter2.Requirements
SpringDataDocument1.xbinariesrequiresJDKlevel6.0andabove,andSpringFramework3.0.xandabove.
Intermsofdocumentstores,MongoDBpreferablyversion1.6.5orlaterorCouchDB1.0.1orlaterarerequired.
Chapter3.AdditionalHelpResources
Learninganewframeworkisnotalwaysstraightforward.Inthissection,wetrytoprovidewhatwethinkisaneasytofollowguideforstartingwithSpringDataDocumentmodule.However,ifyouencounterissuesoryouarejustlookingforanadvice,feelfreetouseoneofthelinksbelow:
3.1.Support
Thereareafewsupportoptionsavailable:
3.1.1.CommunityForum
TheSpringDataforumisamessageboardforallSpringData(notjustDocument)userstoshareinformationandhelpeachother.Notethatregistrationisneededonlyforposting.
3.1.2.ProfessionalSupport
Professional,from-the-sourcesupport,withguaranteedresponsetime,isavailablefromSpringSource,thecompanybehindSpringDataandSpring.
3.2.FollowingDevelopment
ForinformationontheSpringDataMongosourcecoderepository,nightlybuildsandsnapshotartifactspleaseseetheSpringDataMongohomepage.
YoucanhelpmakeSpringDatabestservetheneedsoftheSpringcommunitybyinteractingwithdevelopersthroughtheSpringCommunityforums.TofollowdeveloperactivitylookforthemailinglistinformationontheSpringDataMongohomepage.
Ifyouencounterabugorwanttosuggestanimprovement,pleasecreateaticketontheSpringDataissuetracker.
TostayuptodatewiththelatestnewsandannouncementsintheSpringecosystem,subscribetotheSpringCommunityPortal.
Lastly,youcanfollowtheSpringSourceDatablogortheprojectteamonTwitter(SpringData)
Chapter4.Repositories
4.1.Introduction
Implementingadataaccesslayerofanapplicationhasbeencumbersomeforquiteawhile.Toomuchboilerplatecodehadtobewritten.Domainclasseswereanemicandnotdesignedinarealobjectorientedordomaindrivenmanner.
Usingbothofthesetechnologiesmakesdeveloperslifealoteasierregardingrichdomainmodel'spersistence.Neverthelesstheamountofboilerplatecodetoimplementrepositoriesespeciallyisstillquitehigh.SothegoaloftherepositoryabstractionofSpringDataistoreducetheefforttoimplementdataaccesslayersforvariouspersistencestoressignificantly.
ThefollowingchapterswillintroducethecoreconceptsandinterfacesofSpringDatarepositories.
4.2.Coreconcepts
ThecentralinterfaceinSpringDatarepositoryabstractionisRepository(probablynotthatmuchofasurprise).Itistypeabletothedomainclasstomanageaswellastheidtypeofthedomainclass.Thisinterfacemainlyactsasmarkerinterfacetocapturethetypestodealwithandhelpuswhendiscoveringinterfacesthatextendthisone.Beyondthatthere'sCrudRepositorywhichprovidessomesophisticatedfunctionalityaroundCRUDfortheentitybeingmanaged.
Example4.1.Repositoryinterface
publicinterfaceCrudRepository<T,IDextendsSerializable>
extendsRepository<T,ID>{
Tsave(Tentity);
TfindOne(IDprimaryKey);
Iterable<T>findAll();
Longcount();
voiddelete(Tentity);
booleanexists(IDprimaryKey);
//…morefunctionalityomitted.
}
| Savesthegivenentity. |
| Returnstheentityidentifiedbythegivenid. |
| Returnsallentities. |
| Returnsthenumberofentities. |
| Deletesthegivenentity. |
| Returnswhetheranentitywiththegivenidexists. |
Usuallywewillhavepersistencetechnologyspecificsub-interfacestoincludeadditionaltechnologyspecificmethods.WewillnowshipimplementationsforavarietyofSpringDatamodulesthatimplementthisinterface.
OntopoftheCrudRepositorythereisaPagingAndSortingRepositoryabstractionthataddsadditionalmethodstoeasepaginatedaccesstoentities:
Example4.2.PagingAndSortingRepository
publicinterfacePagingAndSortingRepository<T,IDextendsSerializable>extendsCrudRepository<T,ID>{
Iterable<T>findAll(Sortsort);
Page<T>findAll(Pageablepageable);
}
AccessingthesecondpageofUserbyapagesizeof20youcouldsimplydosomethinglikethis:
PagingAndSortingRepository<User,Long>repository=//…getaccesstoabean
Page<User>users=repository.findAll(newPageRequest(1,20);
4.3.Querymethods
NexttostandardCRUDfunctionalityrepositoriesareusuallyqueriesontheunderlyingdatastore.WithSpringDatadeclaringthosequeriesbecomesafour-stepprocess:
DeclareaninterfaceextendingRepositoryoroneofitssub-interfacesandtypeittothedomainclassitshallhandle.publicinterfacePersonRepositoryextendsRepository<User,Long>{…}
Declarequerymethodsontheinterface.List<Person>findByLastname(Stringlastname);
SetupSpringtocreateproxyinstancesforthoseinterfaces.<?xmlversion="1.0"encoding="UTF-8"?>
<beans:beansxmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/data/jpahttp://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<repositoriesbase-package="com.acme.repositories"/>
</beans>
Gettherepositoryinstanceinjectedanduseit.publicclassSomeClient{
@Autowired
privatePersonRepositoryrepository;
publicvoiddoSomething(){
List<Person>persons=repository.findByLastname("Matthews");
}
Atthisstagewebarelyscratchedthesurfaceofwhat'spossiblewiththerepositoriesbutthegeneralapproachshouldbeclear.Let'sgothrougheachofthesestepsandfigureoutdetailsandvariousoptionsthatyouhaveateachstage.
4.3.1.Definingrepositoryinterfaces
Asaveryfirststepyoudefineadomainclassspecificrepositoryinterface.It'sgottoextendRepositoryandbetypedtothedomainclassandanIDtype.IfyouwanttoexposeCRUDmethodsforthatdomaintype,extendCrudRepositoryinsteadofRepository.
4.3.1.1.Finetuningrepositorydefinition
UsuallyyouwillhaveyourrepositoryinterfaceextendRepository,CrudRepositoryorPagingAndSortingRepository.Ifyoudon'tlikeextendingSpringDatainterfacesatallyoucanalsoannotateyourrepositoryinterfacewith@RepositoryDefinition.ExtendingCrudRepositorywillexposeacompletesetofmethodstomanipulateyourentities.Ifyouwouldratherbeselectiveaboutthemethodsbeingexposed,simplycopytheonesyouwanttoexposefromCrudRepositoryintoyourdomainrepository.
Example4.3.SelectivelyexposingCRUDmethods
interfaceMyBaseRepository<T,IDextendsSerializable>extendsRepository<T,ID>{
TfindOne(IDid);
Tsave(Tentity);
}
interfaceUserRepositoryextendsMyBaseRepository<User,Long>{
UserfindByEmailAddress(EmailAddressemailAddress);
}
InthefirststepwedefineacommonbaseinterfaceforallourdomainrepositoriesandexposefindOne(…)aswellassave(…).ThesemethodswillberoutedintothebaserepositoryimplementationofthestoreofyourchoicebecausetheyarematchingthemethodsignaturesinCrudRepository.SoourUserRepositorywillnowbeabletosaveusers,findsingleonesbyidaswellastriggeringaquerytofindUsersbytheiremailaddress.
4.3.2.Definingquerymethods
4.3.2.1.Querylookupstrategies
Thenextthingwehavetodiscussisthedefinitionofquerymethods.Therearetwomainwaysthattherepositoryproxyisabletocomeupwiththestorespecificqueryfromthemethodname.Thefirstoptionistoderivethequeryfromthemethodnamedirectly,thesecondisusingsomekindofadditionallycreatedquery.Whatdetailedoptionsareavailableprettymuchdependsontheactualstore,however,there'sgottobesomealgorithmthatdecideswhatactualqueryiscreated.
Therearethreestrategiesavailablefortherepositoryinfrastructuretoresolvethequery.Thestrategytobeusedcanbeconfiguredatthenamespacethroughthequery-lookup-strategyattribute.However,Itmightbethecasethatsomeofthestrategiesarenotsupportedforspecificdatastores.Hereareyouroptions:
CREATE
Thisstrategywilltrytoconstructastorespecificqueryfromthequerymethod'sname.Thegeneralapproachistoremoveagivensetofwell-knownprefixesfromthemethodnameandparsetherestofthemethod.ReadmoreaboutqueryconstructioninSection4.3.2.2,“Querycreation”.
USE_DECLARED_QUERY
Thisstrategytriestofindadeclaredquerywhichwillbeusedforexecutionfirst.Thequerycouldbedefinedbyanannotationsomewhereordeclaredbyothermeans.Pleaseconsultthedocumentationofthespecificstoretofindoutwhatoptionsareavailableforthatstore.Iftherepositoryinfrastructuredoesnotfindadeclaredqueryforthemethodatbootstraptimeitwillfail.
CREATE_IF_NOT_FOUND(default)
ThisstrategyisactuallyacombinationofCREATEandUSE_DECLARED_QUERY.Itwilltrytolookupadeclaredqueryfirstbutcreateacustommethodnamebasedqueryifnodeclaredquerywasfound.Thisisthedefaultlookupstrategyandthuswillbeusedifyoudon'tconfigureanythingexplicitly.Itallowsquickquerydefinitionbymethodnamesbutalsocustomtuningofthesequeriesbyintroducingdeclaredqueriesasneeded.
4.3.2.2.Querycreation
ThequerybuildermechanismbuiltintoSpringDatarepositoryinfrastructureisusefultobuildconstrainingqueriesoverentitiesoftherepository.WewillstriptheprefixesfindBy,find,readBy,read,getByaswellasgetfromthemethodandstartparsingtherestofit.AtaverybasiclevelyoucandefineconditionsonentitypropertiesandconcatenatethemwithANDandOR.
Example4.4.Querycreationfrommethodnames
publicinterfacePersonRepositoryextendsRepository<User,Long>{
List<Person>findByEmailAddressAndLastname(EmailAddressemailAddress,Stringlastname);
}
Theactualresultofparsingthatmethodwillofcoursedependonthepersistencestorewecreatethequeryfor,however,therearesomegeneralthingstonotice.Theexpressionsareusuallypropertytraversalscombinedwithoperatorsthatcanbeconcatenated.AsyoucanseeintheexampleyoucancombinepropertyexpressionswithAndandOr.BeyondthatyoualsogetsupportforvariousoperatorslikeBetween,LessThan,GreaterThan,Likeforthepropertyexpressions.Astheoperatorssupportedcanvaryfromdatastoretodatastorepleaseconsulttheaccordingpartofthereferencedocumentation.
4.3.2.2.1.Propertyexpressions
Propertyexpressionscanjustrefertoadirectpropertyofthemanagedentity(asyoujustsawintheexampleabove).Onquerycreationtimewealreadymakesurethattheparsedpropertyisatapropertyofthemanageddomainclass.However,youcanalsodefineconstraintsbytraversingnestedproperties.AssumePersonshaveAddresseswithZipCodes.Inthatcaseamethodnameof
List<Person>findByAddressZipCode(ZipCodezipCode);
willcreatethepropertytraversalx.address.zipCode.Theresolutionalgorithmstartswithinterpretingtheentirepart(AddressZipCode)aspropertyandchecksthedomainclassforapropertywiththatname(uncapitalized).Ifitsucceedsitjustusesthat.Ifnotitstartssplittingupthesourceatthecamelcasepartsfromtherightsideintoaheadandatailandtriestofindtheaccordingproperty,e.g.AddressZipandCode.Ifwefindapropertywiththatheadwetakethetailandcontinuebuildingthetreedownfromthere.Asinourcasethefirstsplitdoesnotmatchwemovethesplitpointtotheleft(Address,ZipCode).
Althoughthisshouldworkformostcases,theremightbecaseswherethealgorithmcouldselectthewrongproperty.SupposeourPersonclasshasanaddressZippropertyaswell.Thenouralgorithmwouldmatchinthefirstsplitroundalreadyandessentiallychoosethewrongpropertyandfinallyfail(asthetypeofaddressZipprobablyhasnocodeproperty).Toresolvethisambiguityyoucanuse_insideyourmethodnametomanuallydefinetraversalpoints.Soourmethodnamewouldenduplikeso:
List<Person>findByAddress_ZipCode(ZipCodezipCode);
4.3.2.3.Specialparameterhandling
Tohandparameterstoyourqueryyousimplydefinemethodparametersasalreadyseenintheexamplesabove.Besidesthatwewillrecognizescertainspecifictypestoapplypaginationandsortingtoyourqueriesdynamically.
Example4.5.UsingPageableandSortinquerymethods
Page<User>findByLastname(Stringlastname,Pageablepageable);
List<User>findByLastname(Stringlastname,Sortsort);
List<User>findByLastname(Stringlastname,Pageablepageable);
ThefirstmethodallowsyoutopassaPageableinstancetothequerymethodtodynamicallyaddpagingtoyourstaticallydefinedquery.SortingoptionsarehandedviathePageableinstancetoo.Ifyouonlyneedsorting,simplyaddaSortparametertoyourmethod.Asyoualsocansee,simplyreturningaListispossibleaswell.WewillthennotretrievetheadditionalmetadatarequiredtobuildtheactualPageinstancebutrathersimplyrestrictthequerytolookuponlythegivenrangeofentities.
| Note |
---|
Tofindouthowmanypagesyougetforaqueryentirelywehavetotriggeranadditionalcountquery.Thiswillbederivedfromthequeryyouactuallytriggerbydefault. |
4.3.3.Creatingrepositoryinstances
Sonowthequestionishowtocreateinstancesandbeandefinitionsfortherepositoryinterfacesdefined.
4.3.3.1.Spring
TheeasiestwaytodosoisbyusingtheSpringnamespacethatisshippedwitheachSpringDatamodulethatsupportstherepositorymechanism.EachofthoseincludesarepositorieselementthatallowsyoutosimplydefineabasepackagethatSpringwillscanforyou.
<?xmlversion="1.0"encoding="UTF-8"?>
<beans:beansxmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/data/jpahttp://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<repositoriesbase-package="com.acme.repositories"/>
</beans:beans>
InthiscaseweinstructSpringtoscancom.acme.repositoriesandallitssubpackagesforinterfacesextendingRepositoryoroneofitssub-interfaces.ForeachinterfacefounditwillregisterthepersistencetechnologyspecificFactoryBeantocreatetheaccordingproxiesthathandleinvocationsofthequerymethods.Eachofthesebeanswillberegisteredunderabeannamethatisderivedfromtheinterfacename,soaninterfaceofUserRepositorywouldberegisteredunderuserRepository.Thebase-packageattributeallowstheuseofwildcards,sothatyoucanhaveapatternofscannedpackages.
Usingfilters
BydefaultwewillpickupeveryinterfaceextendingthepersistencetechnologyspecificRepositorysub-interfacelocatedunderneaththeconfiguredbasepackageandcreateabeaninstanceforit.However,youmightwantfinergrainedcontroloverwhichinterfacesbeaninstancesgetcreatedfor.Todothiswesupporttheuseof<include-filter/>and<exclude-filter/>elementsinside<repositories/>.ThesemanticsareexactlyequivalenttotheelementsinSpring'scontextnamespace.FordetailsseeSpringreferencedocumentationontheseelements.
E.g.toexcludecertaininterfacesfrominstantiationasrepository,youcouldusethefollowingconfiguration:
Example4.6.Usingexclude-filterelement
<repositoriesbase-package="com.acme.repositories">
<context:exclude-filtertype="regex"expression=".*SomeRepository"/>
</repositories>
ThiswouldexcludeallinterfacesendinginSomeRepositoryfrombeinginstantiated.
Manualconfiguration
Ifyou'dratherliketomanuallydefinewhichrepositoryinstancestocreateyoucandothiswithnested<repository/>elements.
<repositoriesbase-package="com.acme.repositories">
<repositoryid="userRepository"/>
</repositories>
4.3.3.2.Standaloneusage
YoucanalsousetherepositoryinfrastructureoutsideofaSpringcontainerusage.YouwillstillneedtohavesomeoftheSpringlibrariesonyourclasspathbutyoucangenerallysetuprepositoriesprogrammaticallyaswell.TheSpringDatamodulesprovidingrepositorysupportshipapersistencetechnologyspecificRepositoryFactorythatcanbeusedasfollows:
Example4.7.Standaloneusageofrepositoryfactory
RepositoryFactorySupportfactory=…//Instantiatefactoryhere
UserRepositoryrepository=factory.getRepository(UserRepository.class);
4.4.Customimplementations
4.4.1.Addingbehaviourtosinglerepositories
Oftenitisnecessarytoprovideacustomimplementationforafewrepositorymethods.SpringDatarepositorieseasilyallowyoutoprovidecustomrepositorycodeandintegrateitwithgenericCRUDabstractionandquerymethodfunctionality.Toenricharepositorywithcustomfunctionalityyouhavetodefineaninterfaceandanimplementationforthatfunctionalityfirstandlettherepositoryinterfaceyouprovidedsofarextendthatcustominterface.
Example4.8.Interfaceforcustomrepositoryfunctionality
interfaceUserRepositoryCustom{
publicvoidsomeCustomMethod(Useruser);
}
Example4.9.Implementationofcustomrepositoryfunctionality
classUserRepositoryImplimplementsUserRepositoryCustom{
publicvoidsomeCustomMethod(Useruser){
//Yourcustomimplementation
}
}
NotethattheimplementationitselfdoesnotdependonSpringDataandcanbearegularSpringbean.Soyoucanusestandarddependencyinjectionbehaviourtoinjectreferencestootherbeans,takepartinaspectsandsoon.
Example4.10.Changestotheyourbasicrepositoryinterface
publicinterfaceUserRepositoryextendsCrudRepository<User,Long>,UserRepositoryCustom{
//Declarequerymethodshere
}
Letyourstandardrepositoryinterfaceextendthecustomone.ThismakesCRUDandcustomfunctionalityavailabletoclients.
Configuration
Ifyouusenamespaceconfigurationtherepositoryinfrastructuretriestoautodetectcustomimplementationsbylookingupclassesinthepackagewefoundarepositoryusingthenamingconventionsappendingthenamespaceelement'sattributerepository-impl-postfixtotheclassname.ThissuffixdefaultstoImpl.
Example4.11.Configurationexample
<repositoriesbase-package="com.acme.repository">
<repositoryid="userRepository"/>
</repositories>
<repositoriesbase-package="com.acme.repository"repository-impl-postfix="FooBar">
<repositoryid="userRepository"/>
</repositories>
Thefirstconfigurationexamplewilltrytolookupaclasscom.acme.repository.UserRepositoryImpltoactascustomrepositoryimplementation,wherethesecondexamplewilltrytolookupcom.acme.repository.UserRepositoryFooBar.
Manualwiring
TheapproachaboveworksperfectlywellifyourcustomimplementationusesannotationbasedconfigurationandautowiringentirelyasitwillbetreatedasanyotherSpringbean.Ifyourcustomimplementationbeanneedssomespecialwiringyousimplydeclarethebeanandnameitaftertheconventionsjustdescribed.Wewillthenpickupthecustombeanbynameratherthancreatinganinstance.
Example4.12.Manualwiringofcustomimplementations(I)
<repositoriesbase-package="com.acme.repository">
<repositoryid="userRepository"/>
</repositories>
<beans:beanid="userRepositoryImpl"class="…">
<!--furtherconfiguration-->
</beans:bean>
Thisalsoworksifyouuseautomaticrepositorylookupwithoutdefiningsingle<repository/>elements.
Incaseyouarenotincontroloftheimplementationbeanname(e.g.ifyouwrapagenericrepositoryfacadearoundanexistingrepositoryimplementation)youcanexplicitlytellthe<repository/>elementwhichbeantouseascustomimplementationbyusingtherepository-impl-refattribute.
Example4.13.Manualwiringofcustomimplementations(II)
<repositoriesbase-package="com.acme.repository">
<repositoryid="userRepository"repository-impl-ref="customRepositoryImplementation"/>
</repositories>
<beanid="customRepositoryImplementation"class="…">
<!--furtherconfiguration-->
</bean>
4.4.2.Addingcustombehaviourtoallrepositories
Inothercasesyoumightwanttoaddasinglemethodtoallofyourrepositoryinterfaces.Sotheapproachjustshownisnotfeasible.Thefirststeptoachievethisisaddingandintermediateinterfacetodeclarethesharedbehaviour
Example4.14.Aninterfacedeclaringcustomsharedbehaviour
publicinterfaceMyRepository<T,IDextendsSerializable>
extendsJpaRepository<T,ID>{
voidsharedCustomMethod(IDid);
}
Nowyourindividualrepositoryinterfaceswillextendthisintermediateinterfacetoincludethefunctionalitydeclared.Thesecondstepistocreateanimplementationofthisinterfacethatextendsthepersistencetechnologyspecificrepositorybaseclasswhichwillactascustombaseclassfortherepositoryproxiesthen.
| Note |
---|
Ifyou'reusingautomaticrepositoryinterfacedetectionusingtheSpringnamespaceusingtheinterfacejustasiswillcauseSpringtocreateaninstanceofMyRepository.ThisisofcoursenotdesiredasitjustactsasintermediarybetweenRepositoryandtheactualrepositoryinterfacesyouwanttodefineforeachentity.ToexcludeaninterfaceextendingRepositoryfrombeinginstantiatedasrepositoryinstanceannotateitwith@NoRepositoryBean. |
Example4.15.Customrepositorybaseclass
publicclassMyRepositoryImpl<T,IDextendsSerializable>
extendsSimpleJpaRepository<T,ID>implementsMyRepository<T,ID>{
publicvoidsharedCustomMethod(IDid){
//implementationgoeshere
}
}
ThelaststeptogetthisimplementationusedasbaseclassforSpringDatarepositoriesisreplacingthestandardRepositoryFactoryBeanwithacustomoneusingacustomRepositoryFactorythatinturncreatesinstancesofyourMyRepositoryImplclass.
Example4.16.Customrepositoryfactorybean
publicclassMyRepositoryFactoryBean<TextendsJpaRepository<?,?>
extendsJpaRepositoryFactoryBean<T>{
protectedRepositoryFactorySupportgetRepositoryFactory(…){
returnnewMyRepositoryFactory(…);
}
privatestaticclassMyRepositoryFactoryextendsJpaRepositoryFactory{
publicMyRepositoryImplgetTargetRepository(…){
returnnewMyRepositoryImpl(…);
}
publicClass<?extendsRepositorySupport>getRepositoryClass(){
returnMyRepositoryImpl.class;
}
}
}
Finallyyoucaneitherdeclarebeansofthecustomfactorydirectlyorusethefactory-classattributeoftheSpringnamespacetotelltherepositoryinfrastructuretouseyourcustomfactoryimplementation.
Example4.17.Usingthecustomfactorywiththenamespace
<repositoriesbase-package="com.acme.repository"
factory-class="com.acme.MyRepositoryFactoryBean"/>
4.5.Extensions
ThischapterdocumentsasetofSpringDataextensionsthatenableSpringDatausageinavarietyofcontexts.CurrentlymostoftheintegrationistargetedtowardsSpringMVC.
4.5.1.DomainclasswebbindingforSpringMVC
GivenyouaredevelopingaSpringMVCwebapplicationsyoutypicallyhavetoresolvedomainclassidsfromURLs.Bydefaultit'syourtasktotransformthatrequestparameterorURLpartintothedomainclasstohanditlayersbelowthenorexecutebusinesslogicontheentitiesdirectly.Thisshouldlooksomethinglikethis:
@Controller
@RequestMapping("/users")
publicclassUserController{
privatefinalUserRepositoryuserRepository;
publicUserController(UserRepositoryuserRepository){
userRepository=userRepository;
}
@RequestMapping("/{id}")
publicStringshowUserForm(@PathVariable("id")Longid,Modelmodel){
//Donullcheckforid
Useruser=userRepository.findOne(id);
//Donullcheckforuser
//Populatemodel
return"user";
}
}
Firstyouprettymuchhavetodeclarearepositorydependencyforeachcontrollertolookuptheentitymanagedbythecontrollerorrepositoryrespectively.Beyondthatlookinguptheentityisboilerplateaswellasit'salwaysafindOne(…)call.FortunatelySpringprovidesmeanstoregistercustomconvertingcomponentsthatallowconversionbetweenaStringvaluetoanarbitrarytype.
PropertyEditors
ForversionsuptoSpring3.0simpleJavaPropertyEditorshadtobeused.Thus,weofferaDomainClassPropertyEditorRegistrar,thatwilllookupallSpringDatarepositoriesregisteredintheApplicationContextandregisteracustomPropertyEditorforthemanageddomainclass
<beanclass="….web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<propertyname="webBindingInitializer">
<beanclass="….web.bind.support.ConfigurableWebBindingInitializer">
<propertyname="propertyEditorRegistrars">
<beanclass="org.springframework.data.repository.support.DomainClassPropertyEditorRegistrar"/>
</property>
</bean>
</property>
</bean>
IfyouhaveconfiguredSpringMVClikethisyoucanturnyourcontrollerintothefollowingthatreducesalotoftheclutterandboilerplate.
@Controller
@RequestMapping("/users")
publicclassUserController{
@RequestMapping("/{id}")
publicStringshowUserForm(@PathVariable("id")Useruser,Modelmodel){
//Donullcheckforuser
//Populatemodel
return"userForm";
}
}
ConversionService
AsofSpring3.0thePropertyEditorsupportissuperseededbyanewconversioninfrstructurethatleavesallthedrawbacksofPropertyEditorsbehindandusesastatelessXtoYconversionapproach.WenowshipwithaDomainClassConverterthatprettymuchmimicsthebehaviourofDomainClassPropertyEditorRegistrar.ToregistertheconverteryouhavetodeclareConversionServiceFactoryBean,registertheconverterandtelltheSpringMVCnamespacetousetheconfiguredconversionservice:
<mvc:annotation-drivenconversion-service="conversionService"/>
<beanid="conversionService"class="….context.support.ConversionServiceFactoryBean">
<propertyname="converters">
<list>
<beanclass="org.springframework.data.repository.support.DomainClassConverter">
<constructor-argref="conversionService"/>
</bean>
</list>
</property>
</bean>
4.5.2.Webpagination
@Controller
@RequestMapping("/users")
publicclassUserController{
//DIcodeomitted
@RequestMapping
publicStringshowUsers(Modelmodel,HttpServletRequestrequest){
intpage=Integer.parseInt(request.getParameter("page"));
intpageSize=Integer.parseInt(request.getParameter("pageSize"));
model.addAttribute("users",userService.getUsers(pageable));
return"users";
}
}
AsyoucanseethenaiveapproachrequiresthemethodtocontainanHttpServletRequestparameterthathastobeparsedmanually.Weevenomittedanappropriatefailurehandlingwhichwouldmakethecodeevenmoreverbose.Thebottomlineisthatthecontrolleractuallyshouldn'thavetohandlethefunctionalityofextractingpaginationinformationfromtherequest.SoweincludeaPageableArgumentResolverthatwilldotheworkforyou.
<beanclass="….web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<propertyname="customArgumentResolvers">
<list>
<beanclass="org.springframework.data.web.PageableArgumentResolver"/>
</list>
</property>
</bean>
Thisconfigurationallowsyoutosimplifycontrollersdowntosomethinglikethis:
@Controller
@RequestMapping("/users")
publicclassUserController{
@RequestMapping
publicStringshowUsers(Modelmodel,Pageablepageable){
model.addAttribute("users",userDao.readAll(pageable));
return"users";
}
}
ThePageableArgumentResolverwillautomaticallyresolverequestparameterstobuildaPageRequestinstance.Bydefaultitwillexpectthefollowingstructurefortherequestparameters:
Table4.1.RequestparametersevaluatedbyPageableArgumentResolver
page | Thepageyouwanttoretrieve |
page.size | Thesizeofthepageyouwanttoretrieve |
page.sort | Thepropertythatshouldbesortedby |
page.sort.dir | Thedirectionthatshouldbeusedforsorting |
IncaseyouneedmultiplePageablestoberesolvedfromtherequest(formultipletablese.g.)youcanuseSpring's@Qualifierannotationtodistinguishonefromanother.Therequestparametersthenhavetobeprefixedwith${qualifier}_.Soamethodsignaturelikethis:
publicStringshowUsers(Modelmodel,
@Qualifier("foo")Pageablefirst,
@Qualifier("bar")Pageablesecond){…}
you'dhavetopopulatefoo_pageandbar_pageandtheaccordingsubproperties.
Defaulting
ThePageableArgumentResolverwilluseaPageRequestwiththefirstpageandapagesizeof10bydefaultandwillusethatincaseitcan'tresolveaPageRequestfromtherequest(becauseofmissingparameterse.g.).Youcanconfigureaglobaldefaultonthebeandeclarationdirectly.IncaseyoumightneedcontrollermethodspecificdefaultsforthePageablesimplyannotatethemethodparameterwith@PageableDefaultsandspecifypageandpagesizeasannotationattributes:
publicStringshowUsers(Modelmodel,
@PageableDefaults(pageNumber=0,value=30)Pageablepageable){…}
PartII.ReferenceDocumentation
DocumentStructure
ThispartofthereferencedocumentationexplainsthecorefunctionalityofferedbySpringDataDocument.
Chapter5,MongoDBsupportintroducestheMongoDBmodulefeatureset.
Chapter6,MongoDBrepositoriesintroducestherepositorysupportforMongoDB.
Chapter5.MongoDBsupport
TheMongoDBsupportcontainsawiderangeoffeatureswhicharesummarizedbelow.
SpringconfigurationsupportusingJavabased@ConfigurationclassesoranXMLnamespaceforaMongodriverinstanceandreplicasets
MongoTemplatehelperclassthatincreasesproductivityperformingcommonMongooperations.IncludesintegratedobjectmappingbetweendocumentsandPOJOs.
ExceptiontranslationintoSpring'sportableDataAccessExceptionhierarchy
FeatureRichObjectMappingintegratedwithSpring'sConversionService
Annotationbasedmappingmetadatabutextensibletosupportothermetadataformats
Persistenceandmappinglifecycleevents
JavabasedQuery,Criteria,andUpdateDSLs
AutomaticimplementatinofRepositoryinterfacesincludingsupportforcustomfindermethods.
QueryDSLintegrationtosupporttype-safequeries.
Cross-storepersistance-supportforJPAEntitieswithfieldstransparentlypersisted/retrievedusingMongoDB
Log4jlogappender
GeoSpatialintegration
FormosttasksyouwillfindyourselfusingMongoTemplateortheRepositorysupportthatbothleveragetherichmappingfunctionality.MongoTemplateistheplacetolookforaccessingfunctionalitysuchasincrementingcountersorad-hocCRUDoperations.MongoTemplatealsoprovidescallbackmethodssothatitiseasyforyoutogetaholdofthelowlevelAPIartifactssuchasorg.mongo.DBtocommunicatedirectlywithMongoDB.ThegoalwithnamingconventionsonvariousAPIartifactsistocopythoseinthebaseMongoDBJavadriversoyoucaneasilymapyourexistingknowledgeontotheSpringAPIs.
5.1.GettingStarted
SpringMongoDBsupportrequiresMongoDB1.4orhigherandJavaSE5orhigher.Thelatestproductionrelease(2.0.xasofthiswriting)isrecommended.AneasywaytobootstrapsettingupaworkingenvironmentistocreateaSpringbasedprojectinSTS.
FirstyouneedtosetuparunningMongodbserver.RefertotheMongodbQuickStartguideforanexplanationonhowtostartupaMongoDBinstance.OnceinstalledstartingMongoDBistypicallyamatterofexecutingthefollowingcommand:MONGO_HOME/bin/mongod
TocreateaSpringprojectinSTSgotoFile->New->SpringTemplateProject->SimpleSpringUtilityProject-->pressYeswhenprompted.Thenenteraprojectandapackagenamesuchasorg.spring.mongodb.example.
Thenaddthefollowingtopom.xmldependenciessection.
<dependencies>
<!--otherdependencyelementsomitted-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>1.0.0.M5</version>
</dependency>
</dependencies>
AlsochangetheversionofSpringinthepom.xmltobe
<spring.framework.version>3.0.6.RELEASE</spring.framework.version>
YouwillalsoneedtoaddthelocationoftheSpringMilestonerepositoryformaventoyourpom.xmlwhichisatthesamelevelofyour<dependencies/>element
<repositories>
<repository>
<id>spring-milestone</id>
<name>SpringMavenMILESTONERepository</name>
<url>http://maven.springframework.org/milestone</url>
</repository>
</repositories>
Therepositoryisalsobrowseablehere.
YoumayalsowanttosettheloggingleveltoDEBUGtoseesomeadditionalinformation,editthelog4j.propertiesfiletohave
log4j.category.org.springframework.data.document.mongodb=DEBUG
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE}%5p%40.40c:%4L-%m%n
CreateasimplePersonclasstopersist
packageorg.spring.mongodb.example;
publicclassPerson{
privateStringid;
privateStringname;
privateintage;
publicPerson(Stringname,intage){
this.name=name;
this.age=age;
}
publicStringgetId(){
returnid;
}
publicStringgetName(){
returnname;
}
publicintgetAge(){
returnage;
}
@Override
publicStringtoString(){
return"Person[id="+id+",name="+name+",age="+age+"]";
}
}
Andamainapplicationtorun
packageorg.spring.mongodb.example;
importstaticorg.springframework.data.mongodb.core.query.Criteria.where;
importorg.apache.commons.logging.Log;
importorg.apache.commons.logging.LogFactory;
importorg.springframework.data.mongodb.core.MongoOperations;
importorg.springframework.data.mongodb.core.MongoTemplate;
importorg.springframework.data.mongodb.core.query.Query;
importcom.mongodb.Mongo;
publicclassMongoApp{
privatestaticfinalLoglog=LogFactory.getLog(MongoApp.class);
publicstaticvoidmain(String[]args)throwsException{
MongoOperationsmongoOps=newMongoTemplate(newMongo(),"database");
mongoOps.insert(newPerson("Joe",34));
log.info(mongoOps.findOne(newQuery(where("name").is("Joe")),Person.class));
mongoOps.dropCollection("person");
}
}
Thiswillproducethefollowingoutput
10:01:32,062DEBUGapping.MongoPersistentEntityIndexCreator:80-Analyzingclassclassorg.spring.example.Personforindexinformation.
10:01:32,265DEBUGramework.data.mongodb.core.MongoTemplate:631-insertDBObjectcontainingfields:[_class,age,name]incollection:Person
10:01:32,765DEBUGramework.data.mongodb.core.MongoTemplate:1243-findOneusingquery:{"name":"Joe"}indb.collection:database.Person
10:01:32,953INFOorg.spring.mongodb.example.MongoApp:25-Person[id=4ddbba3c0be56b7e1b210166,name=Joe,age=34]
10:01:32,984DEBUGramework.data.mongodb.core.MongoTemplate:375-Droppedcollection[database.person]
Eveninthissimpleexample,therearefewthingstotakenoticeof
YoucaninstantiatethecentralhelperclassofSpringMongo,MongoTemplate,usingthestandardcom.mongodb.Mongoobjectandthenameofthedatabasetouse.
ThemapperworksagainststandardPOJOobjectswithouttheneedforanyadditionalmetadata(thoughyoucanoptionallyprovidethatinformation.Seehere.).
Conventionsareusedforhandlingtheidfield,convertingittobeaObjectIdwhenstoredinthedatabase.
Mappingconventionscanusefieldaccess.NoticethePersonclasshasonlygetters.
Iftheconstructorargumentnamesmatchthefieldnamesofthestoreddocument,theywillbeusedtoinstantiatetheobject
5.1.1.RequiredJars
ThefollowingjarsarerequiredtouseSpringDataMongoDB
spring-data-mongodb-1.0.2.RELEASE.jar
spring-data-commons-1.2.0.RELEASE.jar
InadditiontotheabovelistedSpringDatajarsyouneedtoprovidethefollowingdependencies:
aopalliance-1.0.0.jar
commons-logging-1.1.1.jar
mongo-java-driver-2.5.3.jar
spring-aop-3.0.7.RELEASE.jar
spring-asm-3.0.7.RELEASE.jar
spring-beans-3.0.7.RELEASE.jar
spring-context-3.0.7.RELEASE.jar
spring-core-3.0.7.RELEASE.jar
spring-expression-3.0.7.RELEASE.jar
5.1.2.MigratingfromM2toM3
TherewereseveralAPIchangesintroducedintheM3release.ToupgradefromM2toM3youwillneedtomake.ForafulllistingofAPIchangespleaserefertothisJDiffReport.
ThemajorchangesarewithrespecttoMongoTemplate
ConstructorshavechangedonMongoTemplate.MongoTemplate(Mongo,String,String)andMongoTemplate(Mongo,String,String,MongoConverter)wereremoved.MongoTemplate(Mongo,String,UserCredentials),MongoTemplate(MongoDbFactory),MongoTemplate(MongoDbFactory,MongoConverter)wereadded.ThesechangeswillalsoeffectusageofwiringupMongoTemplatein<bean/>XMLdefintions.
MongoTemplatenolongertakesadefaultcollectionname.ThecollectionnameisnoweitherspecifiedwhenthemethodisinvokedorinferredfromtheJavaclass,eithertheclassnameorviamappingmetadata.
ReorderedparametersinsomeMongoTemplatemethodstomakesignaturesmoreconsistentacrosstheboard.
RemovedMongoTemplatemethodsthatuseMongoReaderandMongoWriter.AsanalternativeregisteraSpringconverterwiththeMappingMongoConverter.Seeherefordetails.
AddedfindByIdmethodstoMongoTemplate.
5.2.ExamplesRepository
Thereisangithubrepositorywithseveralexamplesthatyoucandownloadandplayaroundwithtogetafeelforhowthelibraryworks.
5.3.ConnectingtoMongoDBwithSpring
OneofthefirsttaskswhenusingMongoDBandSpringistocreateacom.mongodb.MongoobjectusingtheIoCcontainer.Therearetwomainwaystodothis,eitherusingJavabasedbeanmetadataorXMLbasedbeanmetadata.Thesearediscussedinthefollowingsections.
| Note |
---|
ForthosenotfamiliarwithhowtoconfiguretheSpringcontainerusingJavabasedbeanmetadatainsteadofXMLbasedmetadataseethehighlevelintroductioninthereferencedocshereaswellasthedetaileddocumentationhere. |
5.3.1.RegisteringaMongoinstanceusingJavabasedmetadata
AnexampleofusingJavabasedbeanmetadatatoregisteraninstanceofacom.mongodb.Mongoisshownbelow
Example5.1.Registeringacom.mongodb.MongoobjectusingJavabasedbeanmetadata
@Configuration
publicclassAppConfig{
/**UsethestandardMongodriverAPItocreateacom.mongodb.Mongoinstance.*/
public@BeanMongomongo()throwsUnknownHostException{
returnnewMongo("localhost");
}
}
Thisapproachallowsyoutousethestandardcom.mongodb.MongoAPIthatyoumayalreadybeusedtousingbutalsopollutesthecodewiththeUnknownHostExceptioncheckedexception.TheuseofthecheckedexceptionisnotdesirableasJavabasedbeanmetadatausesmethodsasameanstosetobjectdependencies,makingthecallingcodecluttered.
Analternativeistoregisteraninstanceofcom.mongodb.MongoinstancewiththecontainerusingSpring'sMongoFactoryBean.Ascomparedtoinstantiatingacom.mongodb.Mongoinstancedirectly,theFactoryBeanapproachdoesnotthrowacheckedexceptionandhastheaddedadvantageofalsoprovidingthecontainerwithanExceptionTranslatorimplementationthattranslatesMongoDBexceptionstoexceptionsinSpring'sportableDataAccessExceptionhierarchyfordataaccessclassesannoatedwiththe@Repositoryannotation.Thishierarchyanduseof@RepositoryisdescribedinSpring'sDAOsupportfeatures.
AnexampleofaJavabasedbeanmetadatathatsupportsexceptiontranslationon@Repositoryannotatedclassesisshownbelow:
Example5.2.Registeringacom.mongodb.MongoobjectusingSpring'sMongoFactoryBeanandenablingSpring'sexceptiontranslationsupport
@Configuration
publicclassAppConfig{
/**Factorybeanthatcreatesthecom.mongodb.Mongoinstance*/
public@BeanMongoFactoryBeanmongo(){
MongoFactoryBeanmongo=newMongoFactoryBean();
mongo.setHost("localhost");
returnmongo;
}
}
Toaccessthecom.mongodb.MongoobjectcreatedbytheMongoFactoryBeaninother@Configurationoryourownclasses,usea"private@AutowiredMongomongo;"field.
5.3.2.RegisteringaMongoinstanceusingXMLbasedmetadata
WhileyoucanuseSpring'straditional<beans/>XMLnamespacetoregisteraninstanceofcom.mongodb.Mongowiththecontainer,theXMLcanbequiteverboseasitisgeneralpurpose.XMLnamespacesareabetteralternativetoconfiguringcommonlyusedobjectssuchastheMongoinstance.ThemongonamespacealowsyoutocreateaMongoinstanceserverlocation,replica-sets,andoptions.
TousetheMongonamespaceelementsyouwillneedtoreferencetheMongoschema:
Example5.3.XMLschematoconfigureMongoDB
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation=
"http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/data/mongohttp://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsdhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!--Defaultbeannameis'mongo'-->
<mongo:mongohost="localhost"port="27017"/>
</beans>
AmoreadvancedconfigurationwithMongoOptionsisshownbelow(notethesearenotrecommendedvalues)
Example5.4.XMLschematoconfigureacom.mongodb.MongoobjectwithMongoOptions
<beans>
<mongo:mongohost="localhost"port="27017">
<mongo:optionsconnections-per-host="8"
threads-allowed-to-block-for-connection-multiplier="4"
connect-timeout="1000"
max-wait-time="1500}"
auto-connect-retry="true"
socket-keep-alive="true"
socket-timeout="1500"
slave-ok="true"
write-number="1"
write-timeout="0"
write-fsync="true"/>
</mongo:mongo/>
</beans>
Aconfigurationusingreplicasetsisshownbelow.
Example5.5.XMLschematoconfigurecom.mongodb.MongoobjectwithReplicaSets
<mongo:mongoid="replicaSetMongo"replica-set="127.0.0.1:27017,localhost:27018"/>
5.3.3.TheMongoDbFactoryinterface
Whilecom.mongodb.MongoistheentrypointtotheMongoDBdriverAPI,connectingtoaspecificMongoDBdatabaseinstancerequiresadditionalinformationsuchasthedatabasenameandanoptionalusernameandpassword.Withthatinformationyoucanobtainacom.mongodb.DBobjectandaccessallthefunctionalityofaspecificMongoDBdatabaseinstance.Springprovidestheorg.springframework.data.mongodb.core.MongoDbFactoryinterfaceshownbelowtobootstrapconnectivitytothedatabase.
publicinterfaceMongoDbFactory{
DBgetDb()throwsDataAccessException;
DBgetDb(StringdbName)throwsDataAccessException;
}
ThefollowingsectionsshowhowyoucanusethecontiainerwitheitherJavaortheXMLbasedmetadatatoconfigureaninstanceoftheMongoDbFactoryinterface.Inturn,youcanusetheMongoDbFactoryinstancetoconfigureMongoTemplate.
Theclassorg.springframework.data.mongodb.core.SimpleMongoDbFactoryprovidesimplementstheMongoDbFactoryinterfaceandiscreatedwithastandardcom.mongodb.Mongoinstance,thedatabasenameandanoptionalorg.springframework.data.authentication.UserCredentialsconstructorargument.
InsteadofusingtheIoCcontainertocreateaninstanceofMongoTemplate,youcanjustusetheminstandardJavacodeasshownbelow.
publicclassMongoApp{
privatestaticfinalLoglog=LogFactory.getLog(MongoApp.class);
publicstaticvoidmain(String[]args)throwsException{
MongoOperationsmongoOps=newMongoTemplate(newSimpleMongoDbFactory(newMongo(),"database"));
mongoOps.insert(newPerson("Joe",34));
log.info(mongoOps.findOne(newQuery(where("name").is("Joe")),Person.class));
mongoOps.dropCollection("person");
}
}
ThecodeinboldhighlightstheuseofSimpleMongoDbFactoryandistheonlydifferencebetweenthelistingshowninthegettingstartedsection.
5.3.4.RegisteringaMongoDbFactoryinstanceusingJavabasedmetadata
ToregisteraMongoDbFactoryinstancewiththecontainer,youwritecodemuchlikewhatwashighlightedinthepreviouscodelisting.Asimpleexampleisshownbelow
@Configuration
publicclassMongoConfiguration{
public@BeanMongoDbFactorymongoDbFactory()throwsException{
returnnewSimpleMongoDbFactory(newMongo(),"database");
}
}
Todefinetheusernameandpasswordcreateaninstanceoforg.springframework.data.authentication.UserCredentialsandpassitintotheconstructorasshownbelow.ThislistingalsoshowsusingMongoDbFactoryregisteraninstanceofMongoTemplatewiththecontainer.
@Configuration
publicclassMongoConfiguration{
public@BeanMongoDbFactorymongoDbFactory()throwsException{
UserCredentialsuserCredentials=newUserCredentials("joe","secret");
returnnewSimpleMongoDbFactory(newMongo(),"database",userCredentials);
}
public@BeanMongoTemplatemongoTemplate()throwsException{
returnnewMongoTemplate(mongoDbFactory());
}
}
5.3.5.RegisteringaMongoDbFactoryinstanceusingXMLbasedmetadata
ThemongonamespaceprovidesaconvientwaytocreateaSimpleMongoDbFactoryascomparedtousingthe