티스토리 뷰

개발/안드로이드

Android SQLite Database

임뒤 2017. 10. 27. 11:58

안드로이드의 내부 DB를 사용하는 방법에 대해 알아보자.


우선, 안드로이드에서 Data를 저장하는 방식은 여러가지가 있다.


무엇이 있고, 또 언제 이것들을 사용하는지 알아보자.



위 그림은 Udacity Android App 강좌에서 가져왔다.


1. onSavedInstanceState 요놈은 키밸류 (복잡한 구조 가능 - 클래스 모델 같은거). 근데 얘는 앱이 열려있을 때만 쓸 수 있당. 그래서 앱이 돌아갈 때 데이터를 전달하고 싶다면 이 놈을 이용해도 좋을 듯 (영속성이 없다는 거야.)


2. SharedPreferences 요놈은 우리가 Settings 만들 때 접해봤을 꺼임. 얘도 역시 키밸류 근데 (Primitive 만 된다. int, boolean, String 같은 애들만 된다고) 얘는 영속성 있어서, 앱 끄거나 폰 끄거나 해도 앱을 삭제하지만 않으면 계속 잘 가지고 있단다. 그니까 간단한 세팅 값 같은 것들 들고있거나, 유저들의 이름 요런 간단한 값들은 얘가 처리하면 됨.


3. SQLite Database 얘는 좀 더 복잡한 애 가능해 그니까 테이블 형식으로 구조를 짜서 값을 저장할 수 있단다. 지금 잘해볼 꺼니까 잘 보셈. DB 공부를 잘해놨어야 함. 당연히 영속성 있음.


4. Internal / External storage 얘는 멀티미디어나 큰 사이즈의 데이터 같은거 그니까 사진이나 동영상이나 문서같은거 저장할 때 요기에 접근해서 가져다 쓴단다. 요기에 직접 컨택하는 법은 잘모름. 찾아봐야겠다.


5. Server 말그대로 서버임. 걍 다른 컴터에 저장하는 거니까. 내 폰의 저장소 아님. Client - Server 개념부터 익혀오자.



그래서 지금은, 안드로이드의 Data 저장의 끝판왕인 SQLite Database를 사용해보고자 한다.


사실 이 글을 포스팅하는 이유는, Database의 사용을 위해서가 아니라 Content Provider의 사용을 위해서다.


Database 사용하는 방법을 알지 못하면, Content Provider를 사용할 수 없기 때문이다.


Let's go!




우선, 위의 그림을 이해하자.


1. Contract를 만들자 : 그니까 Contract 한국말로하면 계약서다. Database에 어떻게 계약을 할 껀지 정하는 문서를 만들어야 한다.


2. Helper로 Contract (계약서)에 명시된 내용을 가져와서 Database에 접근하여 CRUD를 해주면 된다. 


3. CRUD가 뭐냐고? (Create, Read, Update, Delete) 다. 



예시 코드를 살펴보자.


1. 계약서 만들기.

package com.rimduhui.sqlitedatabasetutorial;

import android.provider.BaseColumns;

public class TutorialContract {

private TutorialContract() {}

public static class TutorialEntry implements BaseColumns {
public static final String TABLE_NAME = "tutorial";
public static final String COLUMN_NAME_TITLE = "title";
public static final String COLUMN_NAME_SUBTITLE = "subtitle";
}
}

요렇게 한번 만들어봤당. 튜토리얼 계약서다. 튜토리얼 계약서의 제목은 'tutorial' 이고, 그 안에 'title'과 'subtitle'이란 애들로 내용이 채워질 것이다. Great~!



2. Helper 만들기.

package com.rimduhui.sqlitedatabasetutorial;

import android.database.sqlite.SQLiteOpenHelper;

public class TutorialDbHelper extends SQLiteOpenHelper {
}

요렇게 SQLiteOpenHelper를 상속받는다. 그러면 빨간줄이 쳐진다. 왜냐면 수행해줘야 할 메소드들을 안가져왔으니께 그럼 수행해주면, 

package com.rimduhui.sqlitedatabasetutorial;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class TutorialDbHelper extends SQLiteOpenHelper {

public TutorialDbHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}

@Override
public void onCreate(SQLiteDatabase db) {

}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}
}

요렇게 될 것인디, Constructor (생성자)를 보면 파라미터가 4개가 있다. name 이랑 version은 우리가 Contract에서 지정해서 Custom하게 가지고 있을 것이므로, 두개는 뺀다. 고러면 요렇게 된다.



package com.rimduhui.sqlitedatabasetutorial;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class TutorialDbHelper extends SQLiteOpenHelper {

public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "Tutorial.db";

public TutorialDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {

}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}
}

자, 요렇게 하믄 잘혔다. onCreate에서는 DB를 생성해주는 쿼리문을 날리고, onUpgrade에서는 Table이 존재하는 아닌지 여부를 판단한 다음에 존재하면 삭제한다. 그리고 다시 onCreate를 호출해서 새롭게 생성하믄 된다.

package com.rimduhui.sqlitedatabasetutorial;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class TutorialDbHelper extends SQLiteOpenHelper {

public static final int DATABASE_VERSION = 1;
public static final String DATABASE_NAME = "Tutorial.db";

private static final String TEXT_TYPE = " TEXT";
private static final String COMMA_SEP = ",";
private static final String SQL_CREATE_ENTRIES =
"CREATE TABLE " + TutorialContract.TutorialEntry.TABLE_NAME + " (" +
TutorialContract.TutorialEntry._ID + " INTEGER PRIMARY KEY," +
TutorialContract.TutorialEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP +
TutorialContract.TutorialEntry.COLUMN_NAME_SUBTITLE + TEXT_TYPE + " )";

private static final String SQL_DELETE_ENTRIES =
"DROP TABLE IF EXISTS " + TutorialContract.TutorialEntry.TABLE_NAME;

public TutorialDbHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(SQL_CREATE_ENTRIES);
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(SQL_DELETE_ENTRIES);
onCreate(db);
}
}

잘혔다. 그러면 이제 DB에 본격적으로 접근해보자. DBHelper를 인스턴스로 만들어서 CRUD 해주면 된다!



3. CRUD ㄲㄲ


엄청 간단하게 버튼을 4개 넣고, 각각의 버튼은 'C', 'R', 'U', 'D' 의 역할을 한다. 


TextField 두 개에 다가 title과 subtitle을 입력받고, 'C', 'R', 'U', 'D'를 진행한다.


우선 C부터

mTutorialDbHelper = new TutorialDbHelper(this);
SQLiteDatabase db = mTutorialDbHelper.getWritableDatabase();

ContentValues values = new ContentValues();
values.put(TutorialContract.TutorialEntry.COLUMN_NAME_TITLE, mTitle.getText().toString());
values.put(TutorialContract.TutorialEntry.COLUMN_NAME_SUBTITLE, mSubtitle.getText().toString());

long newRowId = db.insert(TutorialContract.TutorialEntry.TABLE_NAME, null, values);
if (newRowId > 0) {
mResult.setText("new Row Id : " + newRowId);
}

일단은 mTutorialDbHelper의 인스턴스를 생성하고,


insert를 하면되는디, ContentValues라는 객체를 통하여 Column에 값을 넣고 저렇게 잘 해주면 된다. 짱 쉽.


다음 R.


얘는 Cursor를 알아야됨. 쉬움 걱정 노노. query를 해서 읽어오면 Cursor라는 객체로 떨어지는데, Cursor라는 객체가 DB의 테이블을 


지정하는 포인터라고 생각하면 됨. 파일포인터처럼 DB를 가르키고 있다는 거임.


보통, 실제적으로 사용할 때 Query문을 사용하려면, AsyncTaskLoader안에 CursorLoader를 사용해서 비동기로 DB를 가지고 옴. 우리는 UI와는 무관하게 Query하여 DB에서 Data를 가져올 가능성이 높기 때문에!


그러면, 코드를 보자.

SQLiteDatabase db = mTutorialDbHelper.getReadableDatabase();

Cursor c = db.query(
TutorialContract.TutorialEntry.TABLE_NAME,
null,
null,
null,
null,
null,
null
);

c.moveToFirst();

if (c.getCount() != 0) {
mResult.setText("title : " + c.getString(c.getColumnIndex(TutorialContract.TutorialEntry.COLUMN_NAME_TITLE)) +
"\nsubtitle : " + c.getString(c.getColumnIndex(TutorialContract.TutorialEntry.COLUMN_NAME_SUBTITLE)));
}

while (c.moveToNext()) {
mResult.append("\ntitle : " + c.getString(c.getColumnIndex(TutorialContract.TutorialEntry.COLUMN_NAME_TITLE)) +
"\nsubtitle : " + c.getString(c.getColumnIndex(TutorialContract.TutorialEntry.COLUMN_NAME_SUBTITLE)));
}

자 요렇게 했음.


U랑 D하기 짱 귀찮다...


U ㄱㄱ

SQLiteDatabase db = mTutorialDbHelper.getReadableDatabase();

ContentValues values = new ContentValues();
values.put(TutorialContract.TutorialEntry.COLUMN_NAME_TITLE, mTitle.getText().toString());
values.put(TutorialContract.TutorialEntry.COLUMN_NAME_SUBTITLE, mSubtitle.getText().toString());

String selection = TutorialContract.TutorialEntry.COLUMN_NAME_TITLE + " LIKE ?";
String[] selectionArgs = { mTargetTitle.getText().toString() };

int count = db.update(
TutorialContract.TutorialEntry.TABLE_NAME,
values,
selection,
selectionArgs);

if (count > 0) {
mResult.setText("Count : " + count);
}

이번엔 살짝 고급지게, Target을 넣어봤음. 업데이트를 어떻게 하냐면, TargetTitle과 Title이 같은 놈이 디비에 있으면 그 놈을 찾아서 걔를 Update해주는 거임 잘혔다. D하고 끝내자.

SQLiteDatabase db = mTutorialDbHelper.getReadableDatabase();

String selection = TutorialContract.TutorialEntry.COLUMN_NAME_TITLE + " LIKE ?";
String[] selectionArgs = { mTargetTitle.getText().toString() };
db.delete(TutorialContract.TutorialEntry.TABLE_NAME, selection, selectionArgs);

얘도 고급지쥬~ ㅋㅋ 타겟에 있는 Title을 찾아서 지우는 거임!


이상 DB사용법 끝!! 다음은 이걸 이용해서 ContentProvider를 Custom하게 만들어보겠음.



전체 프로젝트 받으실려면


https://github.com/rimduhui/android-sqlite-database-tutorial.git


요기로~

'개발 > 안드로이드' 카테고리의 다른 글

Android Different Languages 적용기  (1) 2017.11.15
Android Custom Content Provider  (0) 2017.11.01
Android Content Provider  (0) 2017.10.26
Android Permissions  (0) 2017.10.25
Android Location Api  (0) 2017.10.24
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30