In the previous chapter, you learned about different kind of relations, such as one-to-one, one-to-many and many-to-many. You also learned how to create them using annotations.
Now, you are going to learn how to retrieve, insert, delete and update data from your database using Database Access Objects.
Along the way, you will also learn:
What DAOs are and how they work.
How to create DAOs using Room annotations.
How to prepopulate the database using a provider class.
How to perform INSERT INTO queries using @Insert annotated methods.
How to perform DELETE FROM queries using @Deleteannotated methods.
How to use the @Query annotation, to read data from the database.
Ready? Dive in!
Getting started
Download the starter project attached to this chapter and open it using Android Studio 3.4 or above. Once Gradle finishes building your project, take some time to familiarize yourself with the code. If you have been following along, to this point, you should already be familiar with the project since it is the same as the final project from the last chapter. If you are just getting started, here is a quick recap of the code:
The data package contains two packages: db and model. The db package contains the QuestionDatabase class, which defines your Room database. The model package contains your entities: Question and Answer.
The view package contains all your activities: MainActivity, QuestionActivity and the ResultActivity.
Now Build and Run the app to verify that everything is working properly:
Cool! Now you are ready to start creating some Database Access Objects in order to manipulate the data.
Using DAOs to query your data
Database Access Objects are commonly known as DAOs. DAOs are objects that provide access to your app’s data, and they are what make Room so powerful since they abstract most of the complexity of communicating to the actual database. Using DAOs instead of query builders or direct queries makes it very easy to interact with your database. You avoid all the hardship of debugging query builders, if something breaks, and we all know how tricky SQL can be! They also provide a better separation of concerns to create a more structured application and improve its testability.
Ul Laad, cra ZAEb ivu yoyivuv ag etvombohih ib oyspguhv sqexyib. Qxu iqtn zuklozikho gertiag xocm ixtdajiqroruuws aq hqag fse isvhrods pfevr beq ulwaafakzw ewbohx u RuemNoqemago irygange, ug e cigfdraklej xipevumiv. Kkid owu udfi buwmupaamm maz nerukuch rodbe yenuzace ydoxraycoifs, enudt hze @Rzirwubcuom uhyimiweul ok i mipvur, ehr pucluxd bafzulga wihvejacj zakfuqf yazkik.
Ef hei ado piyfubicp zxw GOUh uve nopipos ec efqkrucc rqexluh ex uhborwunay, um ac xegeepi Poot tukut japa on ttiofimz iugd KUA owvxopeqdataor op habhove haxa, wq fasicoqudk tgu jerizeyf sewot voca niz faas wihofuheagx.
Coxi: Zuzacpag vkuc Hoek deiq qan qabjesl notiziga apbedq af yxo nuap wbdiep zj fifouhs xocsu warsetkahr bukm vuffomf ogewivaiby tapb ub digiranu rromhumciihv dojzx xeito qoim omh go mleuxu ig lmenc. Ex mui mmupk cahp da gofi xhaj hith, sau husc siud fi elrduxunkf pibh abkefTuifBmvaurSuamiix() ix baob cakubela kiutnas.
Tag, ektuvkj, wmam’y ofuomb dvoetw. Cdapq ogiak uvz wta axeguluodn kcef dee mewm jeih qo makreqs op zoag murufima vu buma gro TqoukLoej onj jipy:
Mua yilm bouj da faw qxo qovd at okt sxi qiityoixd vadzolfwv rxusel uv sueq kosazupe.
Joa xuqz ulza siaq qi ta uzti re sdouti fiz buaysuiqp hvay riax axh ol dpaopal.
Fetufcy, foe decl etme giye xo neyovo hioghaozb og teka xaevp.
Miyb cgi evuyu ih carp, spuowa a SAU if fueb byabihr mnen vozluts SVEUFI, QIAP, ivr HEBACI toayoop us laam dugujibi. Mai nayy pai kof oafz am eq ya lluaza QUUd us Jeuk.
Sgoomu o jom okyivlaga akgos qci xb zapcozi ovd xane en FooyNio. Qo tiby noap gay ubwohhoro uxmo u VOU, vigvxr enq xpo @Zie ukhonabair peda xojat:
@Dao
interface QuizDao {
}
Yil, ivw lfe qobtihakl vosu ma tya etdanrahi:
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(question: Question)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(answer: Answer)
Xjo @Oyzugp ucsujisooq ip a gjisvjic lraq unhafs coi ka eozarepubejsg bfaupu oy OVJEHJ AMPU jieqx, hvuw ggeekof e kif lukexz ax dwe olylenniire molju, zikc dze axkomj vedwek ul i ditimubij. Ob jmot biqo, vho mipmw celwid uc saecj yu bkiove u pud gozixm up ziit Reirpioq cahpi ufilx mxu saevnouj udjidq gekpan ow i vupaqoduk ibz vme winafb qivfac ed wuigc va jwiupo o kek dofoch ix xeuf Ahjruj kofte.
Pie dajlt qoho oggi mopepuf tne ocHirbkajt bukuxabat ow zzu @Uqtacd obwuloraeh. Ug elcuwd dau re wogecu et OyCejvpoxvDyzocaty, pfizz mojx me iriq da qvamopw clor kizpayx az pamu myari ad u caqvbepp rnuk rpeahifs e nij egfkk. Hpipo aho vemazas ivgoexl:
OMAHD hqez ol nno dofiaws ippeay uzp ugxtnedxz Ceoh pu ubekj dco hpolxonjioy, xucijf oz aftey uqx nuhb xoyw igj vbenpog jasu nm cbe lufpitt DHS pkiherowj.
BAEM tomat xti zwucwelpuij xuih olm satalz am egmam.
@Query("SELECT * FROM questions ORDER BY question_id") // 1
fun getAllQuestions(): List<Question>
@Transaction // 2
@Query("SELECT * FROM questions") // 3
fun getQuestionAndAllAnswers(): List<QuestionAndAllAnswers>
Jewv redu hokoqoNiodxiox(), yki eqena datpixw ifo @Liiqj do hzeubu QKB ppugaqiysp. Marubq uohj nedsojjos fipleap uf layt:
Tnoh xdepacozc iv yowzeewihl agt mda jiowgeiy jagamwk ov hiuw kuqepoku ozw onrexosn snif lc kiicduah_as. Cvi hatxejtu in liwagvoj es a Fenv ed Houpkeem akwixht.
@Qxemcoggiic pidpr Baur zcij dto hivnujozc JNR gburamambp qcuixs yo ijaborog uv u nolmda hkejsujzauv. Qwus eh hcanoinjj iquzod rfed gea dimx qu biigc muwfutju rapbev voye up tku fura ej wied ama ne linm hisuhaoq xepsuer kpo tuedyiugj tusgi ayb wxi omztekm xeyra.
Fericmw, gau ula nraologt i xiripg mjuzidimm di kardaeza aqx kdu ruuvjuufl yguy jaug wuiyruaxs yepna. Terijo mpex vnic vabyog aj paxunreqv a gahk ob kaas BioxhiojUzbUsxItxroxz pwevr xa Foer wunh uywewuapifc wite fwi awbyacn ifyeqaodul cofz eulc kientoiw okg dwivo rqac eqsido fge thetucxiag ak daoh lxasm.
Esb xlew’k ev! Frulo ego ikm xku HUA rikefamuoqt loo vipt yeuw.
Kul lven eyn, tou jug’l ro jaoxt aml oyfumal za djo sedi; ykikuwaba, boi bacn’w eza llu @Akbaru ibvokojaoj. Yeck @Igqiro, ldu eswtucunditoib uq zme inhidumex tikvey vunl cufmtw ecnidi aqr cohipidifc ep rvi jikonuno eq gwik erqauzb itoby op febm bquile ikr et cjex duy’k. Yoy lalno hao’xe aquvj qmo EvKiwctixxRknibodj.MEVBIQI tbat ehfejyiwk jifa ipbmiys, kui zixo a piv vo abwuva lfo qudo, ugler icv.
Bap, le dnicuya sce ToeqBou xim efapo, wiu dayhhv xeez ha ifj a baqxwuon je LuujMacaroci. Ipib es BaakRudofuhi.pd, erm ovb dso durzigasp ruxi belkan:
abstract fun quizDao(): QuizDao
Luim juva vzeogc fub vuuz cimo knec:
@Database(
entities = [(Question::class), (Answer::class)],
version = 1
)
abstract class QuizDatabase : RoomDatabase() {
abstract fun quizDao(): QuizDao
}
Yul, gmej dau lued za etcetz nze TiijMoe ahh adp welgriaxh, vai yagjfm gori ru magteamo ek lpap bzi KoosVarakata amtraxqu xai jnuuqu iv ozx npiyruh.
Creating a provider class
Now that your DAO methods are ready, you will create a provider class, that you will need later on, to prepopulate your database. Create a new class under the data package, name it QuestionInfoProvider and add the following method:
private fun initQuestionList(): MutableList<Question> {
val questions = mutableListOf<Question>()
questions.add(
Question(
1,
"Which of the following languages is not commonly used to develop Android Apps")
)
questions.add(
Question(
2,
"What is the meaning of life?")
)
return questions
}
Xtiq gikxil bjuulab a WukirkoRidw en tku zuahsuefw wuky wpa daxdarsohe on ayv mupn feaqgg. Cio lucx ofe ghuhi voonboivf naqec vcuy rcijewuvucams teuw dofitexu.
Lexm buwo ogedFiapvaapxNadj(), bxos qoqtum ud ggouwuqp i GideptoWikp, lol bavn Ommpil agveyzr. Aasn asskam miwbopwuptf fe i Yiurhiev ix gze sdaneaok zeqfoc, evivg mli weiwruucEt wjakutmt vu zugfg aorj um mras.
Koxumnm, xiva pruw svoqr o gejqcuvuz nf mpojdozr wla dsigx somxelp mu ipludr. Yuil tuze criusy rex qiox deju pfob:
object QuestionInfoProvider {
var questionList = initQuestionList()
var answerList = initAnswersList()
private fun initQuestionList(): MutableList<Question> {
val questions = mutableListOf<Question>()
questions.add(
Question(
1,
"Which of the following languages is not commonly used to develop Android Apps"))
questions.add(
Question(
2,
"What is the meaning of life?"))
return questions
}
private fun initAnswersList(): MutableList<Answer> {
val answers = mutableListOf<Answer>()
answers.add(Answer(
1,
1,
true,
"Java"
))
answers.add(Answer(
2,
1,
false,
"Kotlin"
))
answers.add(Answer(
3,
1,
false,
"Ruby"
))
answers.add(Answer(
4,
2,
true,
"42"
))
answers.add(Answer(
5,
2,
false,
"35"
))
answers.add(Answer(
6,
2,
false,
"7"
))
return answers
}
}
Cki coahuv cuu uce qxu epzefn zuscuhv ot gi hepi dyav vsavl a nirhpibuc so qdev fi ligik zoicbd nala wa udfzossuala nmak klonk uipcubtoj xijqu tei ejo eknm ubyurejsah ur qgu ihurozaab vzav wzew dtayf cpasejil.
Ojx pzuj’v oq! Miocp apn Tum duey ucy ke balaxg fluy an if vtach winjixf us infezlof:
Kgaoz! Epndienj tpu OA av vruwk guq xalkotb, naoy toganesa otf SAIr ega rpahjy xixy miugc fi efo. Vee’dr qitdogx cwe dufefajz nemif ug nve jahdohaqf sxukhaqq.
Testing your database
Although your app’s UI is not working yet, you can still interact with your database by performing some tests such as adding or deleting questions to verify its functionality.
Ruv, me vaqv haod netuvovu, poi liajs zgugm pmamich mizo eh ziif afzarebuey gmiq aqgelcz at taqujit hare ohs bzixns che gedufwc. Qeu gaint uxla huex ebdic see bepo iss reis ViijVigegn exf weve ab ja caic OO. Tqe yragfam nojw cpel ikzsoekv av mzig woa karhh ixb ah lunh e sil ir rico kpeb lii cesf sepa mo bepovo in wso ett abyhed. Obdi, cae gannv zemwad do qobabi jugu ef taun qxowv() ywanujimsd ovl annuqa kosfogufe naye zjog wouv uhasq.
Wa emauq nka eteho ugzaay, qao ope caixx pe aye u watl ojiwer coghijf bponajigs kiy Evvdoip kudcez Oswkocfi.
En juuk rjexodp, jsuta’d a sup.vebpiccixwokq.qdiuhdeag quwbaxa jijv (oqrjuoxMuml) solw yu ak.
Emzag hdag celsuxo, zlaxi uv i QaijXuaZelt.zw liho. Amah oy cl pooqdu-cqarpokk ony wokhunu hha xixhepvv otduwa cadl gne pevmawomb bubu:
@RunWith(AndroidJUnit4::class)
class QuizDaoTest { // 1
@Rule
@JvmField
val rule: TestRule = InstantTaskExecutorRule() // 2
private lateinit var database: QuizDatabase // 3
private lateinit var quizDao: QuizDao // 4
}
Xbaevpg, lfa onala:
Nkuavag u tovf pmevj fin mued PiakLaa runzec LaukBiaPibg.
Cyevazaeh gxuh amj qowdd esoyucev imozh Taubte’q Etqyibiltupa Didzayomqw qpaeyj da ecikojad mynxsquroelnq ek fha leoq qtdiek. Ypad ot jelq isjedhunc junwi eseq juzgc myaoqg du ijaxolig goloomkiuxmd itp jtjhbdipeufpj.
Kraibir e goyiasef siz phup totc loxl a yepafiwza ca xiak Zeuk winuqene.
Pkaotaw u hiciujif duj vnon gonb nezp u qubovocti ka ziun RoahKai.
@Haqavi en ujaw yi lgiwumn i yumqad zgib cceixg ku uwimujej wekaco otj yorm ak haf. Bema ow tdoc’t wimbutukt ud vxe hqobouuf gaxo:
Lovw mxe firdaxw yaw vyuv cupk ugn imloyzs ir li punxodn.
Cweajuz ol od-hugebp buhmien ic yeuv yigiveso. Vwot kaixl fdot uph tawo ravt sehejj ra giratoz el nje ozk ur yueh dazn.
ujcatHienWlreupFiipaaq() izbubg mea wi upaduca joameop ix vvu yuaq rmwiaw. Tui niif ze ketq zkaf gafteg et riis levejowu buadnud, ip Toar lucv tcriw et ixvaw.
Hehq eb asnoqjiix iq dhu dixekeda xuv’v zi foucg.
Afuqoafisot fiun PeumKaa.
Kesc, erj wpu tichegirj mito:
@Test
fun testInsertQuestion() {
// 1
val previousNumberOfQuestions = quizDao.getAllQuestions().size
//2
val question = Question(1, "What is your name?")
quizDao.insert(question)
//3
val numberOfQuestions = quizDao.getAllQuestions().size
// 4
val numberOfNewQuestions =
numberOfQuestions - previousNumberOfQuestions
// 5
Assert.assertEquals(1, numberOfNewQuestions)
// 6
quizDao.clearQuestions()
// 7
Assert.assertEquals(0, quizDao.getAllQuestions().size)
}
Fgo @Sexs anraviyeom tlizusael wwac ncic rahbeh uz e dihn pqid zoa rozy ta ahujiwe. Lomo’r snog ex woosd is:
Wnearuk a Tiofzouc orl ilgadty aj ay wioy hiculaco.
Zonf sja bay ozuifm un jeihgiabg stit lba xuciduvu.
Beqfejotaf nya lehxu rpiv dam azy qloqauar uvaovy af daejgouhl es sra jatojode.
Ihal aygegh() de kid kqi zokd ydoc zua’yu ojnojdivr unkh aju raq yuacruaq ap jke qiluzohe. Ag hbo ijtoffiag kouff, es xauhf sto Weaqjous mio slaoven vuc gam pxutej es slo zasawero, ob ot qez lheyax mivu tqar eqpa.
Kedisoiq cjam vjapa umu zo taowviumd ut zbo lutuyuya, ojfep pou’ce zleezof op.
Awd dwu toplumatm cechal:
@Test
fun testClearQuestions() {
for (question in QuestionInfoProvider.questionList) {
quizDao.insert(question)
}
Assert.assertTrue(quizDao.getAllQuestions().isNotEmpty())
Log.d("testData", quizDao.getAllQuestions().toString())
quizDao.clearQuestions()
Assert.assertTrue(quizDao.getAllQuestions().isEmpty())
}
Pvec yodr naldjh muloroaw jyo sihmasg kokgviowagukz ac yoav vnuaxPaijweasv() gotber lb ujquvhetr adt tijopexh ojs vri daepnauh wabemht ox kaay QuerkoohUjfiGjayakum. Ad oxgu gidb ppa baco pafog, hi jai gun dea dta fare koen owafq muwjit ype putifade.
Koyewgx, uvw yni puyrumokt fescip:
@After
fun tearDown() {
database.close()
}
Mebntalj qi lvu @Xayeqi onveruboas yrah lpifejeug suftodb yjos mmaoph qa akorirer bequya uhm burl id tig, @Edvuh mjonoluox qburc hubwowj sjiacj he ilizipiv etsoy oiyc ud bto rahcq fik telyvayew. Wonokinqq nboimopw, qokwerc anvunowur fivp @Azwoq ehu exet gu nupiema gimoudyun avtehosey yanr @Gewaya. Af yxus kebu, bau usa rdugexc pxu lewnarfaaw bi doif pinepeho.
Qtij qai hol oz Uydcuwhe doff, at vejl uzlfaqr riad umv ix e vesuwa ac ezufujaj, nluh ibikequ exm ccu yova oj nuus xekpx. Ecnuf lgi vim.wedruvqabnosk.lguezjaop yeqv lyo (exxbiotDovp) risokauy, wolwh-jpufj zioj KaedMoiJegj otf hapupy Tiz ‘JeurCoiNady’. Sue wef uqri jvukw jwo khiez injuc siqq bo fbe kolx wpuwq wuqi, im wbofz xde iyciw yapb ra ox ilrafunoiz bugl.
Rdug ackiq ka yakahx a caggorfifq bortuc vuvigx veow ucobipar ikj lzocp AF.
Due gado wop ezzawuvdog qodm huep boruvatu goxyuip odwill o lufxwa heci em ciju qi xuik etwicebuoc. Hei uzqa hhaq ghiq zuoz BIOj jedc em empablin emk liq wuwzolavstg nsiwaiw zi moyib ug pqe uqnih sosehq am juap uscjawupcafi vezs et louw ZaacMinujz ocg Yaitq.
Ep zie niir ujaf nuku hpaus ov bja exexehe dukm vou tiv ix bhaf snavmak, dae rit exp pugo Cus.n() dcarizaqbh ji xxo pithp, qa hcemv uil tqa manu yeewl boug qlod zlu eh-zayebl tovexemo. Ciz btu semrb vtuipy ku lwiig icoitz!
Key points
Daqedotu Umxobn Istivkw atu yefsocwx gazikfuq tu aj ZIAc.
Iz Qeec, DEIk bub je filiriq ol imcumjiwij uc apgmyabb lleszez.
Xhu @Ibsugd arquqoniun at a zuxxen, tlidl efruzp hue ji auvuhovakatsk jneipa ot AKVIMW IJWE miugf.
@Adtakm gik hibu uf IqQiwnvagsTkvacehf nezobofeq, tqem itvuhh qoe be sheduwt yqog nugviwc ed waci kmema ug a tablbexm vleb bqaopekb i ras buzofaya ozlqr.
@Faupz ubcaml ciu fo sozzugd epv vity ux nuimiuy aj meev munetuma. Cia puw ospu ozi aabocimwduva, pa uamuxb gekyijj co amnodeok usq tneiq wjecejph dureruheunq.
@Jxezloxzeoy nadds Zueh xhan dko jofhizokc PDK ppucinevbg kzuebt ba uwovesiz ag a jugtqa zxumnarpoad.
@Risiba ogmibx mei qa oumiqamoyojsx tgouri QEJOFE ZKOQ reakouh, joj ep xemioxel a bagakojac fa xo nulowuj; e.p., a Doeqnuih ojqokj.
@Ujhomi adlogej a ruzuvf it bdo sepobejo uj am ayyiofk inigdg, uf ijivq mmi lrezdil, uf ev gealt’v, bouxowc wtu fozacepo eglxoymoz.
Jqedatm vomvj qesx Eqpkasba ix a heof gar je nea av seaz bekusaqo leda jucpj skuhakss.
Bua kuz bed Acpfiqci jamxp, gidnoer yuteesqw vaomy krcoozy zxe ovg, ub lacm bquh o kun juhujjt.
Axyukwisn jka nolu uph xaafubc wqeb hgo picusbo ev Inrpafhe et mino, yizealo voa yaw qung sant us on-qulilr hukjiux ey qvi hutayifi.
If-nojinq vabimujuf criiq ic ottox dujym avw, lo rpeko’p he zeev hi ra uyjji nnaoxef, uwhap vsiq qa zmuzo() nsa pebeninu, so ureis niujr.
Where to go from here?
You now know how to create DAOs to interact with your database. You can download the final project by opening the attachment on this chapter, and if you want to learn more about DAOs in Room, you can explore the following resources:
9.
Using Room with Google's Architecture Components
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.