본문 바로가기
Projects/It's My Waye

[It's My Waye] 5. DB 기능 구현 - DAO 작성

by DevJaewoo 2022. 1. 22.
반응형

DAO 작성

이제 이전 글에서 작성한 모델에 접근할 수 있게 해주는 DAO(Data Access Object)를 작성해야 한다.

DAO는 DB와 프로그램 사이의 인터페이스 역할을 수행하여, Model을 DB에 쉽게 저장하고 불러올 수 있도록 해주는 클래스다.

Item엔 Alarm의 FK가 있기 때문에 Alarm DAO부터 작성했다.


AlarmDAO.kt

class AlarmDAO(val context: Context) {

    fun insert(alarm: Alarm): Int {
        val db = DBHelper(context)
        val result = db.insert(Alarm.TableInfo.TABLE_NAME, ContentValues().apply {
            put(Alarm.TableInfo.COLUMN_NAME_FILE_PATH, alarm.filePath)
            put(Alarm.TableInfo.COLUMN_NAME_VOLUME, alarm.volume)
            put(Alarm.TableInfo.COLUMN_NAME_REPEAT_TIMES, alarm.repeatTimes)
            put(Alarm.TableInfo.COLUMN_NAME_INTERVAL, alarm.interval)
        })

        return result
    }

    fun selectAll(): List<Alarm> {
        val db = DBHelper(context)
        val cursor = db.selectAll(Alarm.TableInfo.TABLE_NAME)
        val list: ArrayList<Alarm> = ArrayList()

        while(cursor.moveToNext()) {
            val id = cursor.getInt(0)
            val filePath = cursor.getString(1)
            val volume = cursor.getInt(2)
            val repeatTimes = cursor.getInt(3)
            val interval = cursor.getInt(4)
            val alarm = Alarm(id, filePath, volume, repeatTimes, interval)

            Log.d(TAG, "selectAll: $alarm")
            list.add(alarm)
        }

        return list
    }

    fun select(whereClause: String): Alarm? {
        val db = DBHelper(context)
        val cursor = db.select(Alarm.TableInfo.TABLE_NAME, whereClause)

        if(cursor.moveToNext()) {
            val id = cursor.getInt(0)
            val filePath = cursor.getString(1)
            val volume = cursor.getInt(2)
            val repeatTimes = cursor.getInt(3)
            val interval = cursor.getInt(4)
            val alarm = Alarm(id, filePath, volume, repeatTimes, interval)

            Log.d(TAG, "selectAll: $alarm")
            return alarm
        }
        else {
            return null
        }
    }

    fun update(alarm: Alarm) {
        val db = DBHelper(context)
        val values = ContentValues().apply {
            put(Alarm.TableInfo.COLUMN_NAME_FILE_PATH, alarm.filePath)
            put(Alarm.TableInfo.COLUMN_NAME_VOLUME, alarm.volume)
            put(Alarm.TableInfo.COLUMN_NAME_REPEAT_TIMES, alarm.repeatTimes)
            put(Alarm.TableInfo.COLUMN_NAME_INTERVAL, alarm.interval)
        }

        db.update(Alarm.TableInfo.TABLE_NAME, values, "${BaseColumns._ID} = ?", alarm.id.toString())
    }

    fun delete(id: Int) {
        val db = DBHelper(context)
        db.delete(Alarm.TableInfo.TABLE_NAME, "${BaseColumns._ID} = ?", id.toString())
    }
}

 

작성한 함수의 역할은 다음과 같다.

  • insert: Alarm 객체를 입력받아 DB에 Insert 한다. 입력된 객체의 ID를 반환한다.
  • selectAll: Alarm 테이블의 모든 행을 List<Alarm>으로 변환하여 반환한다.
  • select: where 조건문을 입력받아 조회된 행들 중 가장 첫번째를 Alarm 형태로 반환한다.
  • update: Alarm 객체를 입력받고, 입력 받은 객체의 ID에 해당하는 행을 입력받은 데이터로 바꾼다.
  • delete: ID를 입력받아 해당 ID의 행을 삭제한다.

 

이제 DBHelper에 일일히 쿼리를 날리지 않아도 된다.

작성한 DAO를 사용해 다음과 같이 DB에 저장하고 불러올 수 있다.

val alarmDAO = AlarmDAO(context)
val alarm1 = Alarm("Test1", 1, 1, 1) 

alarmDAO.insert(alarm1)

 

ItemDAO엔 Alarm 변수가 들어가있는데, 이를 AlarmDAO를 통해 조회해줬다.


ItemDAO.kt

class ItemDAO(val context: Context) {

    fun insert(item: Item): Int {
        val db = DBHelper(context)
        val result = db.insert(Item.TableInfo.TABLE_NAME, ContentValues().apply {
            put(Item.TableInfo.COLUMN_NAME_ITEM, item.name)
            put(Item.TableInfo.COLUMN_NAME_ENABLE, if(item.enabled) 1 else 0)
            put(Item.TableInfo.COLUMN_NAME_FK_ITEM_ALARM, item.alarm?.id.toString())
        })

        return result
    }

    fun selectAll(): List<Item> {
        val db = DBHelper(context)
        val cursor = db.selectAll(Item.TableInfo.TABLE_NAME)
        val list: ArrayList<Item> = ArrayList()
        val alarmDAO = AlarmDAO(context)

        while(cursor.moveToNext()) {
            val id = cursor.getInt(0)
            val name = cursor.getString(1)
            val isEnabled = cursor.getInt(2) == 1
            var alarm: Alarm? = null

            if(cursor.getString(3).lowercase(Locale.getDefault()) != "null") {
                alarm = alarmDAO.select("${BaseColumns._ID} = ${cursor.getInt(3)}")
            }

            list.add(Item(id, name, isEnabled, alarm))
        }

        return list
    }

    fun select(whereClause: String): Item? {
        val db = DBHelper(context)
        val cursor = db.select(Item.TableInfo.TABLE_NAME, whereClause)
        val alarmDAO = AlarmDAO(context)

        if(cursor.moveToNext()) {
            val id = cursor.getInt(0)
            val name = cursor.getString(1)
            val isEnabled = cursor.getInt(2) == 1
            var alarm: Alarm? = null

            if(cursor.getString(3).lowercase(Locale.getDefault()) != "null") {
                alarm = alarmDAO.select("${BaseColumns._ID} = ${cursor.getInt(3)}")
            }

            return Item(id, name, isEnabled, alarm)
        }
        else {
            return null
        }
    }

    fun update(item: Item) {
        val db = DBHelper(context)
        val values = ContentValues().apply {
            put(Item.TableInfo.COLUMN_NAME_ITEM, item.name)
            put(Item.TableInfo.COLUMN_NAME_ENABLE, if(item.enabled) 1 else 0)
            put(Item.TableInfo.COLUMN_NAME_FK_ITEM_ALARM, item.alarm?.id.toString())
        }

        db.update(Item.TableInfo.TABLE_NAME, values, "${BaseColumns._ID} = ?", item.id.toString())
    }

    fun delete(id: Int) {
        val db = DBHelper(context)
        db.delete(Item.TableInfo.TABLE_NAME, "${BaseColumns._ID} = ?", id.toString())
    }
}

 

select와 selectAll 함수에 각 개체마다 alarm을 불러와서 저장하도록 구현했다.

이제 item만 조회해도 alarm도 같이 조회되어 똑같은 일을 두번 하지 않아도 된다.

 

다음 시간엔 테스트 코드를 작성해야겠다.

반응형