안드로이드(android) SQLite 데이타 베이스 다루기 |
개발환경 : JDK 1.6, Android 4.2, window 7 32bit, Eclipse Juno |
오늘은 안드로이드 DB 인 SQLite 를 다루는 방법에 대해 기술하기로 한다.
어떤 언어에서나 DB 를 다루는 것은 필수이다. 장기로 보관하고 그것을 다시
효율적으로 꺼내서 다룰수 있어서 프로그램을 다이나믹하게 만들수 있기
때문이다.
안드로이드에서는 DB 외에 저장하는 방법이 여러가지 있다. 그중하나가
SQLite 를 사용하는 것이다. 휴대폰에서 차용한 만큼 심플하고 가볍다.
그리고 안드로이드 프레임웍에서 Help 클래스를 제공한다. 그것이 크게
두가지 클래스를 사용하는데 SQLiteDatabase, SQLiteOpenHelper 이다.
SQLiteOpenHelper 를 상속받은 클래스를 만들것이다. 주요 함수는
onCreate, onUpgrade, onOpen 이며 데이타베이스 생성과 관리, 존재여부에
대한 역활을 한다.
SQLiteDatabase 는 실질적으로 CRUD 를 수행하는데 쓰인다.
http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html
1. 데이타베이스 기능을 수행하기 위한 Contact 클래스 만들기 |
직접 쿼리를 작성해 CRUD 를 하는 것이 아니라 getter 와 setter 메소드가 있는
Contact 클래스를 만들어 기능을 수행할 것이다.
public class Contact { int id; String name; String phone_number; public Contact(){ } public Contact(int id, String name, String phone_number){ this.id = id; this.name = name; this.phone_number = phone_number; } public Contact(String name, String phone_number){ this.name = name; this.phone_number = phone_number; } public int getID(){ return this.id; } public void setID(int id){ this.id = id; } public String getName(){ return this.name; } public void setName(String name){ this.name = name; } public String getPhoneNumber(){ return this.phone_number; } public void setPhoneNumber(String phone_number){ this.phone_number = phone_number; } }
2. CRUD 를 수행할 클래스 작성 |
데이타베이스를 다루기 위해 읽기와 쓰기 함수들이 필요하다.
이런 CRUD 기능을 수행하기 위해 다음 함수들을 추가한다.
// 새로운 contact 추가 public void addContact(Contact contact) {} // 아이디에 해당하는 contact 가져오기 public Contact getContact(int id) { } // 모든 contact 리스트 가져오기 public ListgetAllContacts() { } // 가져온 contact 숫자 가져오기 public int getContactsCount() { } // contact 업데이트 public int updateContact(Contact contact) { } // contact 삭제하기 public void deleteContact(Contact contact) { }
위의 함수를 하나하나 구현해 본다.
(1) 새로운 contact 추가
addContact 함수는 파라미터로 Contact 객체를 넘기게 되어있다.
넘겨받은 Contact 객체의 값을 ContentValues 객체생성후 값을 채워넣는다.
값을 셋팅한 ContentValues 가 데이타베이스에 집어넣기 위한 매개체가 된다.
// 새로운 contact 추가 public void addContact(Contact contact) { SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(KEY_NAME, contact.getName()); // Name 필드명 values.put(KEY_PH_NO, contact.getPhoneNumber()); // phone number 필드명 // 새로운 Row 추가 db.insert(TABLE_CONTACTS, null, values); db.close(); // 연결종료 }
(2) 아이디에 해당하는 Contact 가져오기
여기에서는 id 필드에 값을 넘겨주고 해당하는 하나의 행값을 가져온다.
// 아이디에 해당하는 contact 가져오기 public Contact getContact(int id) { SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.query(TABLE_CONTACTS, new String[] { KEY_ID, KEY_NAME, KEY_PH_NO }, KEY_ID + "=?", new String[] { String.valueOf(id) }, null, null, null, null); if (cursor != null) cursor.moveToFirst(); Contact contact = new Contact(Integer.parseInt(cursor.getString(0)), cursor.getString(1), cursor.getString(2)); return contact; }
(3) 테이블에 포함된 모든 Contact 데이타 가져오기
아이디에 해당하는 데이타를 가져올때 사용한 db.query 와 달리 이번에는
순수한 쿼리를 이용한다. 2번에서 사용한 query 함수를 사용하기 복잡하다면
문자열로 쿼리를 조합해 rawQuery 를 사용하면 될것이다.
// 모든 contact 리스트 가져오기 public ListgetAllContacts() { List contactList = new ArrayList (); // Select All Query String selectQuery = "SELECT * FROM " + TABLE_CONTACTS; SQLiteDatabase db = this.getWritableDatabase(); Cursor cursor = db.rawQuery(selectQuery, null); // looping through all rows and adding to list if (cursor.moveToFirst()) { do { Contact contact = new Contact(); contact.setID(Integer.parseInt(cursor.getString(0))); contact.setName(cursor.getString(1)); contact.setPhoneNumber(cursor.getString(2)); // Adding contact to list contactList.add(contact); } while (cursor.moveToNext()); } return contactList; }
(4) 테이블에 포함된 데이타 숫자 세기
3번에서 사용한 방법과 동일하며 리턴받은 Cursor 객체에서 getCount 함수를
사용해 갯수정보를 가져오면 된다.
public int getContactsCount() { String countQuery = "SELECT * FROM " + TABLE_CONTACTS; SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.rawQuery(countQuery, null); cursor.close(); // return count return cursor.getCount(); }
(5) contact 데이타 업데이트하기
파라미터로 넘겨준 Contact 객체를 업데이트 한다. 업데이트 해야할 contact id 는
포함되어있으므로 getter 함수를 사용해 꺼내쓰면 된다
public int updateContact(Contact contact) { SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(KEY_NAME, contact.getName()); values.put(KEY_PH_NO, contact.getPhoneNumber()); // updating row return db.update(TABLE_CONTACTS, values, KEY_ID + " = ?", new String[] { String.valueOf(contact.getID()) }); }
(6) contact 데이타 삭제하기
파라미터로 넘겨준 Contact 객체에 해당하는 값을 삭제한다. 직접 쿼리를 작성해
삭제하고자 한다면 rawQuery 함수를 사용하면 된다.
public void deleteContact(Contact contact) { SQLiteDatabase db = this.getWritableDatabase(); db.delete(TABLE_CONTACTS, KEY_ID + " = ?", new String[] { String.valueOf(contact.getID()) }); db.close(); }
3. 전체소스 |
전체소스에서는 onCreate 와 onUpgrade 를 구현한 것을 볼수 있다.
onCreate 는 작업을 하기 위한 테이블 생성 쿼리를 수행하는 것이다.
onUpgrade 는 기존에 있던 테이블을 삭제하고 새로 생성한다.
import java.util.ArrayList; import java.util.List; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import com.example.bookmanager.Contact; public class DBContactHelper extends SQLiteOpenHelper { // All Static variables // Database Version private static final int DATABASE_VERSION = 1; // Database Name private static final String DATABASE_NAME = "contactsManager"; // Contacts table name private static final String TABLE_CONTACTS = "contacts"; // Contacts Table Columns names private static final String KEY_ID = "id"; private static final String KEY_NAME = "name"; private static final String KEY_PH_NO = "phone_number"; public DBContactHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } // Creating Tables @Override public void onCreate(SQLiteDatabase db) { String CREATE_CONTACTS_TABLE = "CREATE TABLE " + TABLE_CONTACTS + "(" + KEY_ID + " INTEGER PRIMARY KEY," + KEY_NAME + " TEXT," + KEY_PH_NO + " TEXT" + ")"; db.execSQL(CREATE_CONTACTS_TABLE); } // Upgrading database @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // Drop older table if existed db.execSQL("DROP TABLE IF EXISTS " + TABLE_CONTACTS); // Create tables again onCreate(db); } /** * CRUD 함수 */ // 새로운 Contact 함수 추가 public void addContact(Contact contact) { SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(KEY_NAME, contact.getName()); // Contact Name values.put(KEY_PH_NO, contact.getPhoneNumber()); // Contact Phone // Inserting Row db.insert(TABLE_CONTACTS, null, values); db.close(); // Closing database connection } // id 에 해당하는 Contact 객체 가져오기 public Contact getContact(int id) { SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.query(TABLE_CONTACTS, new String[] { KEY_ID, KEY_NAME, KEY_PH_NO }, KEY_ID + "=?", new String[] { String.valueOf(id) }, null, null, null, null); if (cursor != null) cursor.moveToFirst(); Contact contact = new Contact(Integer.parseInt(cursor.getString(0)), cursor.getString(1), cursor.getString(2)); // return contact return contact; } // 모든 Contact 정보 가져오기 public ListgetAllContacts() { List contactList = new ArrayList (); // Select All Query String selectQuery = "SELECT * FROM " + TABLE_CONTACTS; SQLiteDatabase db = this.getWritableDatabase(); Cursor cursor = db.rawQuery(selectQuery, null); // looping through all rows and adding to list if (cursor.moveToFirst()) { do { Contact contact = new Contact(); contact.setID(Integer.parseInt(cursor.getString(0))); contact.setName(cursor.getString(1)); contact.setPhoneNumber(cursor.getString(2)); // Adding contact to list contactList.add(contact); } while (cursor.moveToNext()); } // return contact list return contactList; } //Contact 정보 업데이트 public int updateContact(Contact contact) { SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(KEY_NAME, contact.getName()); values.put(KEY_PH_NO, contact.getPhoneNumber()); // updating row return db.update(TABLE_CONTACTS, values, KEY_ID + " = ?", new String[] { String.valueOf(contact.getID()) }); } // Contact 정보 삭제하기 public void deleteContact(Contact contact) { SQLiteDatabase db = this.getWritableDatabase(); db.delete(TABLE_CONTACTS, KEY_ID + " = ?", new String[] { String.valueOf(contact.getID()) }); db.close(); } // Contact 정보 숫자 public int getContactsCount() { String countQuery = "SELECT * FROM " + TABLE_CONTACTS; SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.rawQuery(countQuery, null); cursor.close(); // return count return cursor.getCount(); } }
4. DBContactHelper 클래스를 사용해 DB 제어 하기 |
위에서 만든 클래스를 사용해 샘플데이타를 집어넣고 다시 읽어 들여서
Logcat 에서 확인할수 있도록 log 를 출력하는 예제이다.
import java.util.List; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import com.example.bookmanager.comm.DBContactHelper; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DBContactHelper db = new DBContactHelper(this); /** * CRUD Operations * */ // 샘플데이타 넣기 Log.d("Insert: ", "Inserting .."); db.addContact(new Contact("Ravi", "9100000000")); db.addContact(new Contact("Srinivas", "9199999999")); db.addContact(new Contact("Tommy", "9522222222")); db.addContact(new Contact("Karthik", "9533333333")); // 집어넣은 데이타 다시 읽어들이기 Log.d("Reading: ", "Reading all contacts.."); Listcontacts = db.getAllContacts(); for (Contact cn : contacts) { String log = "Id: "+cn.getID()+" ,Name: " + cn.getName() + " ,Phone: " + cn.getPhoneNumber(); Log.d("Name: ", log); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
5. 로그 확인 |
이제 실행해서 제대로 로그가 찍히는지 확인한다.
Logcat 을 통해 제대로 들어가고 불러와 지는지 확인할수 있다.
댓글을 달아 주세요
박충현 2013.05.15 00:11 댓글주소 수정/삭제 댓글쓰기
많은 도움 받고 갑니다.
-박충현-
개초보 2013.08.09 15:58 댓글주소 수정/삭제 댓글쓰기
3. 전체소스에서
86번째 줄에 public List<contact> 에 Contact 입니다 대문자.
87번째 줄에 List<contact> contactList = new ArrayList<contact>(); 모두 Contact 대문자입니다.
이거 때문에
에리너스 2013.09.12 16:01 댓글주소 수정/삭제 댓글쓰기
} <---이 부분에서 에러가 나요 그냥 괄호일 뿐인데 왜 에러가 나는지 모르겠어요...짝도 다 맞는데 왜 이럴까요??
}
</contact></contact></contact>
죄송합니다. 제가 소스 보기를 위해 javascript 툴을 쓰는데
소스카피를 하게 되면 간혹 마지막 부분에 contact 가 들어가는
경우가 생기더라구요. 계속 삭제하는데 왜 또 생기는지 모르겠어요
고쳐 놓도록 하겠습니다 ^^
과달과달 2013.12.09 17:55 댓글주소 수정/삭제 댓글쓰기
정말 많은 도움 받았습니다. 정말 감사합니다 ㅎ
질문이있는데요.
update 나 delete 클래스에서
id 번호를 받아와서 해당 id값을 가진 row를 삭제하려고 하는데 잘 안되네요..
db.delete 라는 클래스가 구현이 안되어있음에도 오류도 안생기는걸 보면 어디선가 상속을 받고있는것 같은데... 어딘지도 모르겠고.. 왜 id값을 인자로 넘기지 않고 contact 클래스를 통째로 넘기고있는지도 잘 이해가 안되네요...
제가 너무 초보라 질문도 제대로 못하겠네요... 제 질문을 이해하셨으면 좋겠습니다ㅠㅠ
하루동안 스스로 해결~!
내장클래스더군요. 객체를 통째로 넘겨주면 알아서 쿼리 작성해서 삭제하더군요 ㅎㅎㅎㅎ
감사합니다 많이 배우고갑니다 ㅎ
오오츠 2014.01.10 10:09 댓글주소 수정/삭제 댓글쓰기
잘 보고 갑니다. 정말 깔끔하게 정리해 놓으셨네요. 거듭 감사드립니다.
초파 2014.04.09 13:18 댓글주소 수정/삭제 댓글쓰기
제가 지금 DB를 delete를 하려는데 delete가 안되고있어서 이렇게 문의드립니다.
Contact contact = new Contact();
db.deleteContact(contact);
혹여 이렇게 구현하는게 이닌건가요?
오류 2014.08.15 19:27 댓글주소 수정/삭제 댓글쓰기
getcount 에서 cursor를 닫고 나서 리턴해서 오류가있네요 .. 수정해주세요 ㅎㅎㅎㅎ
익명 2016.10.27 03:12 댓글주소 수정/삭제 댓글쓰기
비밀댓글입니다
중요한 정보는 암호화되어있겠지만 아무래도 모든 데이터는 DB 에 저장되어 있으니 위험에 노출되었다고 봐야겠죠.