Room을 이용하여 리스트 객체를 데이터베이스에 저장하고자 하였다. 사실 나는 java 언어를 제대로 공부하지 않고 쓰고 있어서 이 문제를 해결하는데 애를 많이 먹었다. float이랑 Float이 다르다는 것도 이번에 알았다. 그리고 내가 저장한 값이 db라는 파일에 그대로 저장되어 있을 줄 알았는데 wal(write-ahead logging) 파일이란 거에 로그 형식으로 기록되어 있는 것도 이번에 알았다. 심지어 정상적으로 저장되고 있었는데 db 파일엔 아무것도 없어서 엄청 헤매기도 했고, Database Inspector를 통해 실시간으로 데이터베이스에 값이 저장되는 것도 처음 알게 되기도 했고. 아무튼 여러 포스팅에 걸쳐 내가 몰랐던 내용을 정리할 계획이고(아 그리고 Object 타입으로 값을 받는 것도 포스팅 해야지..!) 이번 포스팅에서는 bitmap과 list 객체를 저장하는 법에 대해서 알아보고자 한다.
Room을 사용할 때 primitive type이 아닌 다른 타입의 데이터를 저장하기 위해선 Room에서 제공하는 TypeConverter 어노테이션을 사용하면 된다. 리스트나 사용자가 직접 정의한 커스텀 클래스는 Gson이라는 데이터를 json 형태의 문자열로 바꿔주는 직렬화 라이브러리를 사용한다. Room에 데이터를 저장할 때 json 형태의 문자열로 변환하여 저장한 뒤, 꺼낼 때는 다시 원하는 형태의 클래스로 변환하면 된다.
build.gradle(Module)에 다음과 같은 종속성을 추가해준다.
implementation "com.google.code.gson:gson:2.8.6"
Bitmap 형식을 byte[] 형식으로 변환해야 DB에 넣을 수 있다. bitmap -> byte[]로 변환해주는 함수와 byte[] -> bitmap으로 변환해주는 함수 두 개를 작성한다.
public class Converters {
@TypeConverter
public static byte[] fromBitmap(Bitmap bitmap){
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
return outputStream.toByteArray();
}
@TypeConverter
public static Bitmap toBitmap(byte[] bytes){
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
}
}
추상 데이터베이스 클래스에서 TypeConverter의 위치를 알려줘야 한다. 그러니 어노테이션을 아래와 같이 붙여준다.
@Database(entities = com.Detection.faceRecognition.room.PersonalInfo.class, version = 1)
@TypeConverters(com.Detection.faceRecognition.room.Converters.class) // 명시해줘야 컴퓨터가 알아먹는다.
public abstract class PersonalInfoDatabase extends RoomDatabase {
private static PersonalInfoDatabase INSTANCE;
public abstract com.Detection.faceRecognition.room.PersonalInfoDao personalInfoDao();
public static PersonalInfoDatabase getAppDatabase(Context context){
if(INSTANCE == null){
INSTANCE = Room.databaseBuilder(
context, PersonalInfoDatabase.class, "personalInfo-db").build();
}
return INSTANCE;
}
public static void destroyInstance(){
INSTANCE = null;
}
}
Object 객체로 적혀있지만 사실 근본은 float[][]이어서 float[][]으로 캐스팅해준 다음 진행하였다. 직렬화(float[][] -> String), 역직렬화(String -> float[][]) 함수를 만들어준다.
public class Converters {
@TypeConverter
public static String fromFloatList(Object obj){
float[][] f = (float[][])obj;
return new Gson().toJson(f);
}
@TypeConverter
public static Object toFloatList(String value){
Type listType = new TypeToken<float[][]>() {}.getType();
return new Gson().fromJson(value, listType);
}
}
추상 데이터베이스 클래스에서 TypeConverter의 위치를 알려줘야 한다. 그러니 어노테이션을 아래와 같이 붙여준다.
@Database(entities = com.Detection.faceRecognition.room.PersonalInfo.class, version = 1)
@TypeConverters(com.Detection.faceRecognition.room.Converters.class) // 명시해줘야 컴퓨터가 알아먹는다.
public abstract class PersonalInfoDatabase extends RoomDatabase {
private static PersonalInfoDatabase INSTANCE;
public abstract com.Detection.faceRecognition.room.PersonalInfoDao personalInfoDao();
public static PersonalInfoDatabase getAppDatabase(Context context){
if(INSTANCE == null){
INSTANCE = Room.databaseBuilder(
context, PersonalInfoDatabase.class, "personalInfo-db").build();
}
return INSTANCE;
}
public static void destroyInstance(){
INSTANCE = null;
}
}
지금까지 Room을 이용하여 bitmap, list 데이터를 DB에 저장하는 방법에 대하여 알아보았다. 궁금한 점, 수정해야할 점 있으면 댓글 많이 남겨주시기 바랍니다.