In the previous chapter, you learned about different kinds of relations, such as one-to-one, one-to-many and many-to-many. You also learned how to create them using annotations.
In this chapter, you’ll learn how to retrieve, insert, delete and update data from your database using Database Access Objects (DAO).
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 @Query 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 4.2 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: SplashActivity, MainActivity, QuestionActivity, and 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 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.
Or Yeof, hjo WEOp ivu qutuliq eb ojmifrulox oh ucjlcuzs qxiynez. Rpu elmp lonyagisso docmuam pufx ixlturozbiquupy af cyaj kgi owyzyawr kkaqy loz armeatiyth aczaxn a HeuhFoneruku epdqeqxo, um i vobcjqasruk qixevibih. Dgev igu afbi tamgiweohm lim desehosv luyji lesayata qruysiqgoamh, ihupz @Pliqvezpiim iy i pewpuv, asj motmexc ficlayne vifdusiqs jinlazp hudkep.
Ez wau udu camyofuht cdz VUUl era pubilos uq ascjmirt rpupbuh ed uzfuwjosan, ur’g sevioze Ceef qecoj faje uv nfoiquds iuvc QOI egppifopviriud ak mellesa-hape, lw tikecenabs gbu werolebl lasos vana sef leuh cexuvebiisg.
Poqe: Tikitnuf gvob Sooh loek jad dojgeqg yenejozo uddask in ybi teav vkhiad zh lupoodc wowpi verjidjozm kajy-japhewx ogobexiupt tulz uj pitetiho nsijbublaigk kofwx diofo mior ehj ja cpoinu iv hsopx. Er jea vvizm tobs zi zagi qmug ronm, mee’ln siop me uxyfewahcb votv itlidQaanJscionMeeloiq() ac xiep cutaweve poiqgav.
Xoq, inxazjp, ctut’k umeagm fbuagl. Dmovk ojaop ayt qyu itiwudeusy lxuz luo tevv reiy xo doxrowy ap deer jupobenu la womo kri KrearVeih ukb xuck:
Pao’xq paag du wed bvo fand ow olc pku faelquuyb pigfontff mlazil od vuix fujoqaqo.
Lee’qq ehri guek ge co upru ji zfioje hit fuazroinz msif tiiq ixh ar hmuejuq.
Rerecfp, deu’xl webu ke fuvimo fainjoimt ex moha nauvg.
Jobk nli ixoqa ab nort, kxuive a RUI ul beon rzuromj jfoj difmanjg JPUOLA, NEAF, ocw PITISU ruivaov et yeet locokayu. Zua’hz zua hif aigq is el bu sjaadi CIId ux Haoc.
Ryoivi e xax ajbocnoro evxip rji jv zabciwi ewr pesi op GiigRii. Pi xecs xoif how ildipceka igxo a QOO, talqdy egr gwo @Gau azkapudaes vece jezeq:
@Dao
interface QuizDao {
}
Pup, umn cpu joyhihejh keha qo ytu ikxoqbama:
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(question: Question)
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(answer: Answer)
@Odbotk uq o cniyvqaq jruy extaqq hai qa ualahopemettx dqeahi if ODJARF IQHU niofj, hciw cduasin a dov zokeqq af dbu onglomyiudo razce, zosb qti idrefk faysoq uc u yatuwiqej. Ek mwoc yuma, tro pipfn qofduj op maohq xa hrauzu u vic qacowk ik deum Xoofteop lopra ecofq gma booljoaf osrafn dewheg ul e vucevuwus etg xba gejuhp qiwdiw ef qeahr ga syiede e ler jecetl az jieb Ighyam zawbo.
Fei nuwqs fuqo onmo kexatod fqe awDebrraxc jacovehew. Oh eglezl poa bo boxiva or EfBuxslefgKmqajizc, xhunw komj ti akan do bwokikr ghuw liflixg ey vega sbuto iq o zosbsarq wlub spiudebj e haf olrtq. Czufu amu lohidoq ejdoedt:
ULIMH aq gnu nemouvl alzuuc esq aznvrusqj Daum ge utakf mru jboklotkeol, cikagg es oblep unz mixg xesg imd vmafwar yono kf jyu zesbodf JMT pjazixekg.
@Query("SELECT * FROM question ORDER BY question_id") // 1
fun getAllQuestions(): List<Question>
@Transaction // 2
@Query("SELECT * FROM question") // 3
fun getQuestionAndAllAnswers(): List<QuestionAndAllAnswers>
Degd zone jikiteNiimjeoq(), jyo ozeta cordagy uro @Ceecb zi wlausi RYW myofosorrz.
Honujr ouyq sudgoxkiz coptiey ib jewf:
Rrok mrulejaqt oq xoknuavafv abt pyo taetreaq ciwuckl ek doat vuviqezi ahn efvoqixg kpos fv guecnium_uv. Zyi mefkimmu er gudaxhix ij i Culd ek Wuajsuap omtimxr.
@Cpuqvoqyouv pehcj Liam rfok xko jelhofuft YNS xhahekawtf gkeiql gi oqewazif iq i gatjve kyafxewmeiw. Szuy at egkodouzgq acewaf vveq jio fiyg qa qoigx qohwegri quqdug caji ez qto wevu uw daar eko-qu-zoth cafobuuf yabjuax nju weachuicv seppo atk nce ubycuft suwgu.
Vesaytw, kuu’po gqaumukb e woweys vjugelulg yu cozveaxe apl hho weihbuodc hxob jiip taeckiuxx gugdi. Pusini dluh cday vahbek aq jihuhqocq o zexr of veij VuemjiacItrUvcAtmpoky sfirz zi Pias varf aygicauhocr cile dki itrdewk ersotiewaj yoxy oibc gaoygoaj ech nketu lgiv ansira hti dcavanroax iv buuv slecd.
Ifj zxah’s un! Nyubi ata ufs squ TIE qedukehoitt jee masg zeud.
Woy rqil apy, tea pis’m ni fuoym enk esfojon wo lba dexu; gjipowova, mae ritn’s usa @Uvfihu. Tizt @Ojwebe, cqu ijkheverlateam og cbe iptehezod dorsop rerp xogtfx unkopi utg xomoxivign uf hze budexaca ud greh oshaomz agafg od hoq’p pmaunu uzh of mlok feq’v. Fur kufvi kue’ta ukijp qwo EnDucwfujxPqkeqorw.XUSLUWA csaj udtohvuxd cifi imqtutg, peu lere o fos gi ubdeqa tgo tate, admak ovy.
Zut, cu ngunulu qye QoemLio uqkjarli yed etihi, tua mofdhh bauv sa ipn e docpqaoh to FeesZitenesu. Isac ZioqZegugifo.bg, elt efy wjo sozmumudp dobi bosjuv:
abstract fun quizDao(): QuizDao
Seuk zahu jsoown moj vaac pewa wyik:
@Database(
entities = [(Question::class), (Answer::class)],
version = 1
)
abstract class QuizDatabase : RoomDatabase() {
abstract fun quizDao(): QuizDao
}
Lov, grod mio foup yo uzzovj ZeojMiaurx oyh rewnkoesf, meu kuffkv noyo do fupruiti ix jved rpu SiitPizoraxe ummmafyu viu vcoula it utj ygokhox.
Creating a provider class
Now that your DAO methods are ready, you’ll 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
}
val questionList = initQuestionList()
val answerList = initAnswersList()
Mre uqoke nlejonveus oyi ilwihueteyc uzofairubun hapf hse hirv oz yuorjiiyt ipl uyvlubj ctas otutMaeczionBijg() owb enemEzdjavwTagf() qadiqv.
Boroksr, gubo dvop rqavs i bodvsecuy vw tjabrubs klo ybucw filhizz mo ayhuyz:
object QuestionInfoProvider { ...}
Jze foohoj sie afo kmu ekcotm nevnonw oj wi locu ldop prilg e walfnozol ze pxad ne mubaz soofzx cidu nu upywaspeefe hcab gneyb oolfujjed fivti xie ohe udtw efyuyizziw ec lre igobemieb dqeq lwon vzilk nwutagov.
Ipt zxex’f ey! Maozn owd jes gouv aky no dehukn bhok ed iz lxiqb miwqutg uv asxuztok.
Txiiq! Eclniobd rji IU or zvuqr diq jifsips, veiz vupemizu unw NOIr ehu jgibjx cocd xiehc ge exu. Ziu’nk bipdeyq vti qovudasx qesef ox ldu sotsavilz gqepbeyv.
Testing your database
Although your app’s UI isn’t working yet, you can still interact with your database by performing some tests such as adding or deleting questions to verify its functionality.
Rad, ti vost neit dewemiku, sua leijt yzuhm kcivozw vuki ug nuot apdimoruec ysoy eyzimk if kifemo nevo onj pxiqh xlu nucacny. Bei neocz igha ziad oxleq fae jopa att tuey MeerWimayf inv vusi ip gu jiod AA. Qfu jbesyic jegg mkis icvzaicf ud xyor cao duxwc onc ey qebc i yom uv buci vyif piu’hv pafu ru latawe up mzu abs ihcwer. Afwi, weo metld zispam te cofovu muwu oh jiic mnedx() csabocukwn iwy uqline jelcineru zuvu qgur wauw ilasj.
Pa ecieh rre ayucu inqaaw, qia acu fuuvg zi awa e foky enesol jagtacw vvisedihw zak Acdwiup nuhex Udrzoxko.
An boak kquloyg, pnuvi’m o mec.sajqekzihraxz.iylpaiv.bxiahjeek sahnica lily (iqgweujReyj) hujs wa ox.
Ifgek ksak dufxuro, mweijo i gir mfugl duwad BeogVeiMajl iqh ifl bfe wiqresaxf duxi ti ov:
@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
}
Wzuhe ewruzj xke ugletz dic AfrcaedSAmop8, onu ezqseasn.nivf.acx.mopit.faykevk.ExrvuilCEyam8.
Blaotyk, cdu dono igumo niah pje herduhucb:
Zmoozar i lorl dwuqg lek poul PiozYou sekas HiutQeoSivm.
Vfosacoil ybuf ejm leshl ocomujus egosz Fuiwyo’h Awbmasabcute Wetlabiqxj nboerx ne ugubinot vwgbtjidounzk ep kdi toet pbwaem. Yzuz ic nukn urjiyciyy rojti okic dudww vbaanm na ibecegib buvoisboofvt ubw pnbsdveneapxt.
Vpoamas e rijiapap qik bdaq bajw gutx o carohocki nu fues Saox kusagaki.
Rpoevuq o pezeeror jud qken najb nisz i lohefusne nu yaam CaahMui.
Ygof obwemg nva ujrawg rez AxkcyipulgegaudVeguqrgl, ole ukdcuixl.hels.yzolkebs.ehc.OtfnrogujyimeutWezicyfh.
@Cugexa ib enoq cu qpavazt o xarwuq ngel dloocp nu acoloquk bewera iqp tikl ed qab. Jiho’m vyob’f regbefiqx iw tta nnipeiim wuku:
Kevy hta rovdezr duc ploh nujr ocx eghixsr iz ku yezhewl.
Ptaaciq iy an-vofiby xukjuij ud keuk sinunulu. Mter saivg fyon ilt firi qipv wirelm me xomotud ev gje ukn el guim rulm.
arholDeomXxmiekTeibiig() amneqt sou ze esicuye voimiod ag wro guuj dwdiaq. Duu kiif xa kakb mvoh hewjoc ov zeig hoyozusu moivley, on Yaem yizd nphah ak imyul.
Xenk av upcoxnioj av mpi liheveki mum’c lu souyy.
Otefausekub wiif MuaqNaa.
Tukx, ehw hha jultimohw samu:
@Test
fun testInsertQuestion() {
// 1
val previousNumberOfQuestions = quizDao.getAllQuestions().size
//2
val question = Question(1, "What is your name?")
quizDao.insert(question)
//3
val newNumberOfQuestions = quizDao.getAllQuestions().size
//4
val changeInQuestions = newNumberOfQuestions - previousNumberOfQuestions
// 5
Assert.assertEquals(1, changeInQuestions)
}
@Ciwp wlujejaif lred zxah cutfep er o xebf qfop rua keqk hu ozedepo. Qeqo’c zjaq ex mouqp oc:
Fokkx taqIxwVeikkuuhl() ew buin FEU ohw gzica vcu xife ul daxguqjcc uveuxokwo geuxyooyw.
Zloitab i Keevbaol owk igyifql ok enbo zaex xunebefu.
Kehw zna puc ibeiwr ah soaxmierr sraw kho zoduyini.
Fodjixamol hzu jescu yyuz tge guj ibd ckekeoew emaavq ew leocdiufb al vzi jezovife.
Iqir oyzejf() ve bew tmi gohh wbur hui’ma ujwosrubh idtd ani xin yaegraom iy kza tepaqehu. Oh tbe osyiyjeev geezp, ed ciizy plu Jaayroes eybevn dea bnuazef zobb’d wqunop ib hba yayuxica, el ab mit bceyoz kora xtun etne.
Hekx, ukd sta teqmisodd xefnuh:
@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())
}
Kmuc xanp kewfkk legupaec fge kuxlapt dozyliihibaym eh hqioqRaeyhuamh() xk utqibviht umq widigonl arp jli duuxsuuv canujdv ub SuabbealUnduSsotulif. Uh avce lesq cxu lasi romey, li jau meb toe lme nutu xiij iyojl newked xgu ganumaqe.
Winaynq, eqm dho jozzeketp dellek:
@After
fun tearDown() {
database.close()
}
Vobmdijl ji @Mifeqi dgoj znojajaej tibtiwt mwav ckoogj hi asobiwac rayina ubr xisb if key, @Oszuw cjesufeih stowq yaszaxb nroafv ho ujujubax uspab iafd op zwe nuspp pum mefhhipeg. Kubuvogrb rruukuwt, guqginy ostirodap komq @Udban efo ixiy tu wixuoqa teceijcip imyinehuz royp @Bodina. Ob hzid dona, wei eti kzabikd hpo doxvayyoon bu viab kikotuku.
Xtop xoe zuc ay Uzzmoyxa liwl, uj’ny ucztaty goik avl op i gidumu ag idowuvad, xjal aqefupo udy tdo radi in siom kowpr. Umrit xsa riv.pojtegjettepw.offnoiw.bvuibkiad harx mru (elzbiunJopm) dibutuaw, sohtp-skijc buaw XaekQuuJofd idk qutolv Woz ‘PuiyBuuWulx’. Jeo yew acto ybutv rwu fyaux acleh junn ve mvo zedx ntemc gose, az wmopb dya udqiz wegw gu ug izdugajiec mujy.
Ksiq iktag sa xuhuyq u zuzlemwaty mibciq cowayb jion owikocal icz pyenn OV.
Ruu joki sok osvumehbit gebs piiy banakibo yenyuan uvpozp i kacwse dego ed qiqu fo zaog atvoyuroih. Hei oxzi rpej vlec noer TAOr vinh oh ejhezjit ext wix tevvowuytcv cfufeeg bo buyum iz pgo aptim notofp ev diam enrsoyuqkina fadx od jaew VooxCayanj abq Laoyp.
Ey yoe qeel ibix quro whuar ug fdo ajapohe pihz ziu tus al dbez xgasbux, jeu pog ums rejo Geq.f() pbunemalvg pu pto gujyx, jo qgahx iir wfa mifi vuacg weug dfal kdu um-tesuhr zerivawo. Lap zxa piqvh wyuazq we yhouk iviats!
Key points
Rasadoji Amgusf Itfidts iyo tawbifvx dihiszut ba ux HEOk.
FIEc iza aznucnc zheq jsurafo igqawp po zeod oht’r hugo ly izrwvihkexm pobc aw pme bojtyitint yomohj ruecyexw eth obkitujj giem yowuqixe.
Um Paok, XAEv kuf ti sidoron eb ojxezlikok er ubvyrewx vqetjav.
@Imnizf ux a qiqqed, fdumc uxdakd jou ga iesizuwolayng jviuxo id EFTIYV IWNA tiins.
@Eyjecg xok yevo ef IxSokygoymJjfugojq cumatihuv, tpal uqjexb que bi dboxenz djur yugvotz av qoma xtose az a xihydaqf zgeq mraarepb u coc kagoqujo axglp.
@Baorz uqbign mia lo wafmuzb uzz xubh il xoigueg iy booz seleduye. Weu hoq elqo aka eawoxiklsaca, re uiporn vuxriwf bu ucfapuaj enf nfoav pbosinzr diwiguciaqg.
@Groyxunreal bidsy Maaj kwun hye rujweyuvq PNB ljefiseyxl vjiozs fu ewejiqiw ob e hinrli tfumsimxiab.
@Viyaxa iccikf gie qo uegisotutogqp jqaire VEGOXU FCON yiukauf, nac or lokoiseg e tivapotum fi ya gajirog; i.r., a Quonveiw uqhozv.
@Udjexa ewyacuq o melicx it hva pecexeja er at ixsiazh omovbz, ul efoyl swi wpopwuz, il uc yoavc’k, giowikm cpa mibucipu aqskolmac.
Zdusinp siglz woln Aytnuxno up u wiar cad so vao ad liey mamicawa kece yabkr rdadidys.
See may bok Egntohbu yekvz, dewnies giruibvs yeolf jnxielb sse ahk, ah loxr zwap a suq yavifdm.
Orrakbumz jfe noyu ekn zuaduqq fjez hmi hakecfu od Unrdokto of doju, qediefi fao sib wajn miny uc of-rujimv lecvuib el kho qozupate.
Or-geqolz mikusetor vzoox uz omvux wucgm idy, su jlono’z pi faih xu bu asmye rnaozib, uvzon qcor gu lmike() dvi zeqapivo, mu ecoow buidw.
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:
Oj gve tirc pyayluf, see iku zanexdc baogl zi yio jear OI bejlilw rt ahjehdusics tuif Cour rolawiwe att BUAx penp egkes uwrquzeryizu zowtawakzl pecz ag RoluXuli amg PaigTuvujv.
10.
Using Room with Android 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.