ORM은 object-relational-mapping으로, 객체와 관계형 데이터베이스의 데이터(Tabel)을 mapping하고 변환하는 기술이다.
해당 기술로 복잡한 쿼리를 잘 몰라도 코드만으로 데이터베이스의 모든 것을 컨트롤할 수 있도록 도와준다.
Room 지속성 라이브러리는 SQLite를 완벽히 활용하면서 원활한 데이터베이스 액세스가 가능하도록 SQLite의 추상화 계층을 제공한다.
따라서 SQLite API를 사용하는 것 보다는 Room을 사용하는 것이 좋다.
build.gradle 파일에 다음 종속 항목을 추가한다.
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt'
}
...
dependencies {
def room_version = "2.5.1"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
}
database class / 데이터베이스 클래스: 데이터베이스를 보유하고 앱의 영구 데이터와의 기본 연결을 위한 기본 액세스 포인트 역할을 한다.
Data entities / 데이터 항목: 앱 데이터베이스의 테이블을 나타낸다.
Data access objects (DAOs) / 데이터 액세스 객체(DAO): 앱이 데이터베이스의 데이터를 쿼리, 업데이트, 삽입, 삭제하는 데 사용할 수 있는 메서드를 제공한다.
출처 : 안드로이드 공식문서
https://developer.android.com/training/data-storage/room?hl=ko
@Entity(tableName = "room_memo")
class RoomMemo {
@PrimaryKey(autoGenerate = true)
@ColumnInfo
var no: Long? = null
@ColumnInfo
var content: String = ""
@ColumnInfo(name = "date")
var datetime: Long = 0
constructor(content: String, datetime: Long) {
this.content = content
this.datetime = datetime
}
} //Entity 생성 예제
@Entity @PrimaryKey @ColumnInfo
DAOs 는 데이터베이스에 접근하여 DML쿼리 (SELECT, INSERT, UPDATE, DELETE)를 실행하는 메서드의 모음이다.
Room은 데이터베이스를 읽고 쓰는 메서드를 '인터페이스 형태'로 사용한다. 코드 없이 이름만 명시하는 형태로, 인터페이스를 만들면 Room이 자동으로 나머지 코드를 생성한다.
<인터페이스 정의하기>
@Dao
interface RoomMemoDao {
@Query("select * from room_memo")
fun getAll(): List<RoomMemo>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(memo: RoomMemo)
@Delete
fun delete(memo: RoomMemo)
}
@Query @Insert @Delete
위의 코드에서 INSERT Annotation의 경우 옵션으로
'(onConflict = OnConflictStrategy.REPLACE)'을 적용했다.
이 옵션을 적용 시 동일한 키를 가진 값이 입력된 경우 UPDATE 쿼리로 실행된다. 이처럼 Room에서의 Annotation의 종류를 다음에 설명하겠다.
*Annotation이란 : 사전적 의미로는 주석, JAVA에서는 코드 사이 주석처럼 쓰이며 특별한 의미나 기능을 수행하도록 하는 기술이다. 프로그램에게 추가적인 정보를 제공해주는 메타데이터(meta-data : 데이터의 데이터)이다.
Annotation | 위치 | 옵션 | 설명 |
---|---|---|---|
@Database | 클래스 | entities, version | Database |
@Entity | 클래스 | (tablename = "테이블 명") | Table |
@Columninfo | 멤버 변수 | (name = "컬럼 명") | Column |
@PrimaryKey | 멤버 변수 | (autoGenerate = true) | Column Option |
@Dao | 인터페이스 | 실행 메서드 Interface | |
@Query | 멤버 메서드 | ("쿼리") | 쿼리 직접 작성 및 실행 |
@Insert | 멤버 메서드 | (onClick = REPLACE) | 중복 시 수정 |
@Delete | 멤버 메서드 | 삭제 |
@Entity (tableName = StudentEntity.TABLE_NAME) : Table 이름을 선언하는 Annotation이다. (기본적으로 entity class 이름을 database table 이름으로 인식합니다.)
@PrimaryKey : 각 Entity는 최소 1개의 Primary Key를 가져야 한다.
@ColumnInfo : Table 내 Column을 변수와 매핑시켜주는 Annotation이다.
@Insert : @Entity로 정의된 class만 인자로 받거나, 그 class의 collection 또는 array만 인자로 받을 수 있다. 인자가 하나인 경우 long type의 return (insert 된 row ID)을 받을 수 있고, 여러 개인 경우 long [ ], List를 받을 수 있다.
@Update : @Entity Table의 데이터 수정. Return 값으로 업데이트된 행 수를 받을 수 있다.
@Delete : @Entity Table의 데이터 삭제. Return 값으로 삭제된 행 수를 받을 수 있다.
@Query : @Entity Table의 데이터 조회. Comple time에 return 되는 object의 field와 sql 결과로 나오는 column의 이름이 맞는지 확인하여 일부가 match 되면 warning, match 되는 게 없다면 error를 보낸다.
참고자료 : https://zibro.tistory.com/24
Room에서 제공하는 RoomDatabase 클래스를 상속받아서 추상 클래스를 생성한다.
@Database(entities = arrayOf(RoomMemo::class), version = 1, exportSchema = false)
abstract class roomDatabase: RoomDatabase() {
abstract fun roomMemoDao(): RoomMemoDao
}
@Database
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
private lateinit var roomDB: roomDatabase
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContenView(binding.root)
roomDB = Room.databaseBuilder(this, roomDatabase::class.java, "romm_memo")
.allowMainThreadQueries()
.build()
}
Room 실습 예제 참고 : https://github.com/limsaehyun/Velog-Example/tree/main/RoomExample