Android

[Android] Room 데이터 베이스

poppy 2020. 12. 18. 21:22
반응형

오늘은 ListView와 Room을 사용해 데이터베이스에 대해 다뤄보겠습니다!

 

Room 이란?

- Room은 ORM(Object Relational Mapping) 라이브러리입니다. Room은 데이터베이스의 객체를 자바나 코틀린 객체로 매핑해주는것 입니다. Room은 SQLite의 추상레이어 위에 제공하고 있으며 SQLite의 모든 기능을 제공하면서 데이터베이스 접근을 편하게 해줍니다.

 

Room과 SQLite 차이점?

- SQLite 경우 쿼리에 대한 에러를 컴파일에 확인하는것이 없지만 Room에서는 컴파일 도중 SQL에 대한 유효성을 검사 가능합니다

- 스키마가 변경이 될경우 SQL쿼리를 수동으로 업데이트 해야하지만 Room의 경우는 쉽게 해결이 가능합니다.

- SQLite 경우 Java데이터 객체를 변경하기위해 많은 상용구 코드를 사용해야하지만 ROOM의 경우 ORM라이브러리가 t상용구 코드없이 매핑 가능합니다.

 

Room 구성요소

- Database : 데이터베이스 보유자입니다.

- Entity : Database 내의 테이블을 뜻합니다. 

- Dao : 데이터베이스에 엑세스하는데 사용되는 메소드들을 갖고있습니다. select, insert, delete, join...등 데이터를 관한 처리를 할 수 있습니다.

 

 

1. Room Gradle 설정

Room을 사용하기 위해 build.gradle의 dependencies에 다음 문장들을 추가해줍니다.

def room_version = "2.2.5"

    implementation "androidx.room:room-runtime:$room_version"
    annotationProcessor "androidx.room:room-compiler:$room_version"

2. Entity를 만들어 줍니다 - Song.java

@Entity
public class Song {
    @PrimaryKey(autoGenerate = true) //값 자동으로 생성
    public int id;

    @ColumnInfo(name = "title")
    public String title;

    @ColumnInfo(name = "singer")
    public String singer;
}

3. Dao를 만들어줍니다 - SongDao.java

@Dao
public interface SongDao {
    @Query("SELECT * FROM song") //전체 조회
    List<Song> getAll();

    @Query("SELECT title FROM song") //title만 조회
    List<String> getTitleAll();

    @Query("SELECT singer FROM song") //singer만 조회
    List<String> getSingerAll();

    @Insert
    void insertAll(Song... songs);

    @Delete
    void delete(Song song);
}

4. Database를 만들어줍니다 - SongDatabase.java

@Database(entities = {Song.class}, version = 1)
public abstract class SongDatabase extends RoomDatabase {
    private static SongDatabase INSTANCE; //객체는 하나만 생성
    public abstract SongDao songDao();

    public static SongDatabase getAppDatabase(Context context){
        if(INSTANCE == null){
            INSTANCE = Room.databaseBuilder(context, SongDatabase.class , "song-db").allowMainThreadQueries().build();
        }
        return  INSTANCE;
    }
}

allowMainThreadQueries() - Room을 사용할 때 쿼리 호출은 메인스레드에서 처리하면 안되기 때문에 원래는 비동기처리를 위해 다른 조치를 취해줘야 합니다. 여기서는 테스트용이기 때문에 메인스레드에서 쿼리 호출을 임시로 허용했습니다.

 

5. 뷰를 만들어줍니다 - activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/et_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginTop="20dp"
        android:ems="10"
        android:hint="노래 제목"
        android:inputType="textPersonName"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/et_singer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="20dp"
        android:layout_marginTop="20dp"
        android:ems="10"
        android:hint="가수 이름"
        android:inputType="textPersonName"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_title" />

    <Button
        android:id="@+id/btn_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="60dp"
        android:layout_marginEnd="40dp"
        android:text="확인"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <ListView
        android:id="@+id/lv_songs"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_marginTop="140dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

6. 데이터베이스에 저장된 값을 가져오고, 데이터를 추가할 수 있도록 해줍니다 - MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        EditText et_title = (EditText)findViewById(R.id.et_title);
        EditText et_signer = (EditText)findViewById(R.id.et_singer);
        Button btn_add = (Button)findViewById(R.id.btn_add);
        ListView lv_songs = (ListView)findViewById(R.id.lv_songs);

        List<String> list = new ArrayList<>();
        // 데이터베이스를 가져옴
        SongDatabase songDatabase = SongDatabase.getAppDatabase(this);

        //데이터베이스에 저장된 값을 가져옴
        List<String> title_list = songDatabase.songDao().getTitleAll();
        List<String> singer_list = songDatabase.songDao().getSingerAll();
        String[] title_array = title_list.toArray(new String[title_list.size()]);
        String[] singer_array = singer_list.toArray(new String[singer_list.size()]);

        //가져온 값을 리스트뷰에 추가
        for(int i=0; i<title_array.length; i++){
            list.add(title_array[i] + " - " + singer_array[i]);
        }

        //어댑터 연결
        ArrayAdapter<String> adapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,list);
        lv_songs.setAdapter(adapter);

        btn_add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String title = et_title.getText().toString();
                String singer = et_signer.getText().toString();

                if(title.equals(""))
                    Toast.makeText(getApplicationContext(),"제목을 입력하세요", Toast.LENGTH_SHORT);
                if(singer.equals(""))
                    Toast.makeText(getApplicationContext(),"가수를 입력하세요", Toast.LENGTH_SHORT);

                //데이터 추가
                if(!title.equals("") && !singer.equals("")){
                    Song new_song = new Song();
                    new_song.title = title;
                    new_song.singer = singer;
                    songDatabase.songDao().insertAll(new_song);

                    adapter.notifyDataSetChanged();
                }
            }
        });
    }
}

 

실행화면

 

반응형