안녕하십니까? 오늘 강좌에서부터는 저희가 개발하고 있는 Hangul2English App에 Database 코드를 붙이도록 하겠습니다.

전체 강좌 목차

[강좌A01] Moteodev Studio를 이용한 안드로이드 개발 환경 구축 가이드
[강좌A02] 안드로이드 개발 참고 서적 소개
[강좌A03] Android 실전 개발 - 아이디어 / 기획 / Wireframe
[강좌A04] 안드로이드 실전 개발 - 아이콘 제작
[강좌A05] 안드로이드 실전 개발 - 레이아웃 및 리소스 : Part1
[강좌A06] 안드로이드 실전 개발 - 레이아웃 및 리소스 : Part2
[강좌A07] 안드로이드 실전 개발 - 리소스 해킹
[강좌A08] 안드로이드 실전 개발 - SQLite

[강좌A09] 안드로이드  실전 개발 - 데이터베이스 : Part1

일반적으로 Android database 개발은 다음과 같이 구분할 수 있습니다.

데이터베이스 생성 방식에 따라
1.Code에서 DDL문 실행 – 일반적인 방식. 간단하고 초기 적재해야 될 데이터가 적은 경우.
2.Assets 폴더에 DB를 생성한 후 실행시에 DB 파일을 복사해서 처리하는 방식 – 초기 데이터가 많거나 DB구조가 복잡할 때 주로 사용함.

데이터베이스 관련 소스 처리 방식에 따라
1.Contents Provider – DB를 다른 어플과 공유해야 할 때, 혹은, 여러명이 개발할 때 주로 사용하는 방식으로 DB 처리를 별도의 Provider로 제공하는 방법
2.직접 DB Access – 직접 DB에 query를 실행하여 처리하는 방식

저희가 개발하는 App은 단 하나의 테이블만 필요하고 초기 데이터로는 샘플로 2~3개의 레코드만 등록한 채 개발할 것이므로 Code에서 직접 DDL을 실행하는 방식으로 개발하도록 하겠습니다. 또한, 혼자서 개발하며, 타 App과 DB를 공유해야 할 필요가 없어서 Content Provider로 개발하지 않고, 개발하기 편리한 직접 Access 방식으로 개발 하도록 하겠습니다.

먼저, 저희가 생성할 데이터베이스 스키마 정보는 다음과 같습니다.

Database Name : han_to_eng_db

/* table ddl */
CREATE TABLE TB_DATA (
_ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, /*시퀀스, 자동채번 */
C_KOR_TEXT TEXT, /*한글 저장용*/
C_ENG_TEXT TEXT /*영문 저장용*/
);

/* unique index */
CREATE UNIQUE INDEX TB_DATA_PK ON TB_DATA (_ID);

한글/영문을 저장할 수 있는 테이블 하나와 유니크 인덱스를 하나 만들겁니다. _id 컬럼명은 안드로이드에서 BaseColumn Interface에 정의되어 있는 컬럼명으로 대부분의 코드에서 integer key column name으로 많이 사용합니다. 그래서 저도 _id를 사용하긴 했으나, 맘에 드시는 다른 컬럼명을 사용하셔도 좋습니다. 컬럼명의 “C_”는 컬럼을 구분하기 위한 prefix인데, 없어도 무방합니다. 암튼 저는 위의 DDL문을 기준으로 테이블 및 인덱스를 생성하겠습니다.

먼저, src/ 디렉토리에 다음과 같은 Constants.java 파일을 생성합니다. 이 Constants 클래스는 모든 로그에 들어갈 공통 상수를 정의하겠습니다.

//Constants.java

package com.overoid.hangul2english;

 

public class Constants {

 // Log Class 인자로 넘겨줄 Tag 정의

    public static final String LOG_TAG = "Hangul2English";

}



다음은 데이터베이스쪽 코드입니다.
일반적으로 대부분의 책 및 Android Source Sample에 나타나는 SQL 관련 코드 구조는 다음과 같습니다. 많이들 보셨을 겁니다.


public class DBHelper {

 

/* public static final DB Name, Table Name, Column Name 등을 정의하는 부분 */

 

    private SQLiteDatabase db;

    private final DBOpenHelper dbOpenHelper;

 

   

    public static class <To클래스> {

    /* Transfer Object 사용될 Bean Class 정의*/

    }

   

    /* 데이터베이스 생성. 업데이트, 연결 등의 기능을 제공하는 SQLiteOpenHelper 상속 클래스 정의*/

    private static class DBOpenHelper extends SQLiteOpenHelper {

 

        public DBOpenHelper(final Context context) {

            super(context, DBHelper.DB_NAME, null, DBHelper.DB_VERSION);

        }

 

        @Override

        public void onCreate(final SQLiteDatabase db) {

        /* 테이블 생성, 인덱스 생성, 초기 데이터 적재 코드 */

        }

 

        @Override

        public void onOpen(final SQLiteDatabase db) {

            super.onOpen(db);

        }

 

        @Override

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

        /* 업그레이드시에 처리해야 DDL 실행 */

        }

    }

 

    public DBHelper(final Context context) {

        this.dbOpenHelper = new DBOpenHelper(context);

        establishDb();

    }

 

    private void establishDb() {

        if (this.db == null) {

            this.db = this.dbOpenHelper.getWritableDatabase();

        }

    }

 

    /* 데이터 조회/등록/수정/삭제 관련 코드 왕창 추가*/

}

 


위 코드는 대부분의 안드로이드 샘플이나 책에서 소개하는 데이터베이스 코드 스타일입니다. DBHelper Class 안에 Transfer Object로 사용할 Bean Class와 데이터베이스 생성, 업그레이드, 연결등을 담당할 SQLiteOpenHelper 클래스를 상속하는 클래스 정의, 실제 사용자 DB에서 조회하고 등록,수정, 삭제 등을 처리할 메소드를 모두 DBHelper 클래스 안에 두어 이 파일 하나만 만들면 DB 관련 모든 작업을 할 수 있습니다.

제가 처음 안드로이드 개발할 때 이 방식을 사용했었는데, 단점은 한 파일의 소스코드가 무지 길어진다는 점과 여러 개의 Activity 에서 DB 처리를 해야 할 경우 DB가 Close 되지 않은 상태에서 다른 액티비티에서 Open할 때 에러가 나서 Activity 상태 변화 이벤트 처리 부분이나 select/insert/update/delete 등의 메소드 처리 부분에서 db를 close/open을 해 줘야 에러를 피할 수 있다는 점입니다.

그래서 저는 이 소스 패턴을 조금 변경하도록 하겠습니다.

소스는 향후 재사용성(Copy & Paste)을 높이는데 초점을 두겠습니다. 또한, 여러 Acticity에서 DB Handling시에 Connection 관련 에러를 막기 위해서 SQLiteDatabase 객체를 Singleton으로 만들겠습니다.
또한, DDL문과 Table, Column 정의 부분을 별도의 클래스로 작성하도록 하겠습니다.

먼저 데이터베이스 스키마를 정의하는 클래스 소스입니다. 클래스명은 데이터베이스명(Hangul2English = H2e) + “Database”라고 명명하겠습니다.

//H2eDatabase.java

package com.overoid.hangul2english.data;

 

public final class H2eDatabase {

   

    H2eDatabase() {}

   

    /* Table이나 View마다 중첩 클래스를 만듭니다.

     * 테이블명, 컬럼명 정보를 상수로 정의합니다.

     */

    public static final class DataTable {

        private DataTable() {}

       

        public static final String TABLE_NAME = "TB_DATA";

       

        public static final String COLUMN_ID = "_id";

        public static final String COLUMN_KOR_TEXT = "c_kor_text";

        public static final String COLUMN_ENG_TEXT = "c_eng_text";

       

        public String[] getColumnNames() {

            String[] columnNames = {COLUMN_ID,COLUMN_KOR_TEXT,COLUMN_ENG_TEXT};

            return columnNames;

        }

    }

}



H2eDatabase Class 내에 중첩 클래스로 각 테이블마다 클래스를 만듭니다. 저희는 하나의 테이블이라서 DataTable Class 하나만 내부에 존재하면 됩니다.
클래스명은 <테이블명 식별자> + “Table” 이라고 짓습니다. 그리고 TABLE_NAME 상수와 각 컬럼명을 “COLUMN “ + “_” + <컬럼명 식별자> 로 기술하며, SELECT문에서 사용하기 편리하도록 컬럼명 배열을 리턴하는 getColumnNames 메소드를 추가합니다.

다음은 DDL문 생성을 위한 interface를 하나 만들겠습니다. 구지 interfaces는 없어도 상관없지만, 상속 받는 클래스에서 코드도 편리하게 할 수 있고, 일관성을 유지할 수 있기 때문에 interface를 사용했습니다. Interface의 내용은 별거 없습니다. 생성할 DB명과 DB버전 상수정보와, 각각의 DDL문 배열을 리턴하는 메소드가 선언되어 있습니다.

//DatabaseCreator.java

package com.overoid.hangul2english.data;

 

public interface DatabaseCreator {

   

    public static final String DB_NAME = "han_to_eng_db";

    public static final int DB_VERSION = 1;

   

    /* Table Definition Statement */

    public String[] getCreateTablesStmt();

   

    /* Index Definition Statement */

    public String[] getCreateIndexStmt();

   

    /* View Definition Statement */

    public String[] getCreateViewStmt();

   

    /* Trigger Definition Statement */

    public String[] getCreateTriggerStmt();

   

    /* Initial Data Insert Statement */

    public String[] getInitDataInsertStmt();

}



다음은 실제 DDL문을 리턴하는 DatabaseCreator 인터페이스를 구현하는 클래스입니다.

//H2eDatabaseCreator.java

package com.overoid.hangul2english.data;

 

import com.overoid.hangul2english.data.H2eDatabase.DataTable;

 

public class H2eDatabaseCreator implements DatabaseCreator {

 

   

    /* Table Creation DDL */

    private final String TABLE_CREATE_DATATABLE = "CREATE TABLE "

        + DataTable.TABLE_NAME + " ( "

        + DataTable.COLUMN_ID + " INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "

        + DataTable.COLUMN_KOR_TEXT + " INTEGER, "

        + DataTable.COLUMN_ENG_TEXT + " TEXT); ";

       

   

    /* Index Create DDL */

    private final String INDEX_CREATE_DATATABLE = "CREATE UNIQUE INDEX "

        + DataTable.TABLE_NAME + "_pk ON "

        + DataTable.TABLE_NAME + " (" +  DataTable.COLUMN_ID + " );";

   

    @Override

    public String[] getCreateTablesStmt() {

        String[] tableStmt = {TABLE_CREATE_DATATABLE};

        return tableStmt;

    }

 

    @Override

    public String[] getCreateIndexStmt() {

        String[] indexStmt = {INDEX_CREATE_DATATABLE};

        return indexStmt;

    }

 

    @Override

    public String[] getCreateViewStmt() {

        // TODO Auto-generated method stub

        return null;

    }

 

    @Override

    public String[] getCreateTriggerStmt() {

        // TODO Auto-generated method stub

        return null;

    }

 

    @Override

    public String[] getInitDataInsertStmt() {

        String[] initData = new String[2];

        String[][] initValue = {{"사랑","tkfkd"},

                                {"깍쟁이","Rkrwoddl"}};

 

        for(int i=0; i<2; i++) {

            initData[i] = "INSERT INTO " + DataTable.TABLE_NAME + "("

                         + DataTable.COLUMN_KOR_TEXT + ","

                         + DataTable.COLUMN_ENG_TEXT + " ) "

                         + " VALUES( "

                         + "'" + initValue[i][0] + "','" + initValue[i][1] + "');";

        }

        return initData;

    }

 

}

 

각각의 DDL문을 상수로 정의한 다음 DatabaseCreator 인터페이스 구현 메소드에서 각각의 DDL 문장 배열을 리턴하도록 작성합니다.

나머지 소스들이 내용이 많아서 다음 파트에서 나머지 내용을 계속 진행하도록 하겠습니다.

  1. jordan retro 13 2012.03.05 17:58

    총괄 은 미국 의 인기 는 패션 여성복 브랜드 나인 의 창시자 토 리 버 치 (총괄) 여사.

  2. jordan retro 12 2012.03.05 17:59

    총괄 은 미국 의 인기 는 패션 여성복 브랜드 나인 의 창시자 토 리 버 치 (총괄) 여사.

+ Recent posts