1. SQLite 프로그래밍
안드로이드에서 사용하는 SQLite는 관계형 데이터베이스
1) 안드로이드 앱 개발을 위한 SQLite 동작 방식
🐰 안드로이드 앱에서 SQLite를 사용할 때는 일반적으로 SQLiteOpenHelper 클래스, SQLiteDatabase 클래스, Cursor 인터페이스를 이용
- SQLiteOpenHelper 클래스를 상속받아 새로운 클래스를 생성
- 생성한 클래스에는 데이터베이스 파일과 테이블을 생성하는 내용을 코딩
- SQLiteOpenHelper 클래스의 getWritableDatabase()를 사용하면 SQLiteDatabase를 반환받고, execSQL() 또는 rawQuery() 등으로 SQL문을 실행
- 특히 SELECT문은 Cursor 인터페이스를 반환받은 후에 반복해서 테이블의 행 데이터에 접근
각 클래스에서 자주 사용되는 메서드
클래스 또는 인터페이스 | 메서드 | 주요 용도 |
SQLiteOpenHelper 클래스 | 생성자 | DB 생성 |
onCreate() | 테이블 생성 | |
onUpgrade() | 테이블 삭제 후 다시 생성 | |
getReadableDatabase() | 읽기 전용 DB 열기. SQLiteDatabase 반환 | |
getWritableDatabase() | 읽고 쓰기용 DB 열기. SQLiteDatabase 반환 | |
SQLiteDatabase 클래스 | execSQL() | SQL문 (insert / update / delete) 실행 |
close() | DB 닫기 | |
query(), rawQuery() | select 실행 후 커서 반환 | |
Cursor 인터페이스 | moveToFirst() | 커서의 첫 행으로 이동 |
moveToLast() | 커서의 마지막 행으로 이동 | |
moveToNext() | 현재 커서의 다음 행으로 이동 |
2. 가수 그룹의 이름과 인원을 데이터베이스에 입력하고 조회하는 응용 프로그램 작성
xml 코드
바깥 리니어 레이아웃 안에 리니어레이아웃(수평) 4개를 만들고 다음과 같이 화면 구성.
리니어 레이아웃 1 ~ 3은 layout_weight를 1로, 리니어 레이아웃 4는 8로 설정.
- 리니어 레이아웃 1 : 텍스트뷰 1개, 에디트 텍스트 1개 (editName)
- 리니어 레이아웃 2 : 텍스트뷰 1개, 에디트 텍스트 1개 (editNumber)
- 리니어 레이아웃 3 : 버튼 3개 (btnInit, btnInsert, btnSelect)
- 리니어 레이아웃 4 : 에디트 텍스트 2개 (editNameResult, editNumberResult)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical">
<LinearLayout
android:id="@+id/layout01"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="이름"
android:textSize="20dp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/editName" />
</LinearLayout>
<LinearLayout
android:id="@+id/layout02"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="인원"
android:textSize="20dp"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/editNumber" />
</LinearLayout>
<LinearLayout
android:id="@+id/layout03"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal"
android:gravity="center_horizontal">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:text="초기화"
android:id="@+id/btnInit" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:text="입력"
android:id="@+id/btnInsert" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="조회"
android:id="@+id/btnSelect" />
</LinearLayout>
<LinearLayout
android:id="@+id/layout04"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_weight="8"
android:gravity="center_vertical"
android:background="#FBF4D1">
<EditText
android:id="@+id/editNameResult"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"/>
<EditText
android:id="@+id/editNumberResult"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"/>
</LinearLayout>
</LinearLayout>
MainActivity
class MainActivity : AppCompatActivity() {
lateinit var myHelper: MyDBHelper
lateinit var editName: EditText
lateinit var editNumber: EditText
lateinit var editNameResult: EditText
lateinit var editNumberResult: EditText
lateinit var btnInit: Button
lateinit var btnInsert: Button
lateinit var btnSelect: Button
lateinit var sqlDB: SQLiteDatabase
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setTitle("가수 그룹 관리 DB")
editName = findViewById(R.id.editName)
editNumber = findViewById(R.id.editNumber)
editNameResult = findViewById(R.id.editNameResult)
editNumberResult = findViewById(R.id.editNumberResult)
btnInit = findViewById(R.id.btnInit)
btnInsert = findViewById(R.id.btnInsert)
btnSelect = findViewById(R.id.btnSelect)
myHelper = MyDBHelper(this)
btnInit.setOnClickListener {
sqlDB = myHelper.writableDatabase
myHelper.onUpgrade(sqlDB, 1, 2)
sqlDB.close()
}
btnInsert.setOnClickListener {
sqlDB = myHelper.writableDatabase
sqlDB.execSQL("INSERT INTO `groupTBL` VALUES ('${editName.text.toString()}', " +
"${editNumber.text.toString()});")
sqlDB.close()
Toast.makeText(applicationContext, "입력됨", Toast.LENGTH_SHORT).show()
}
btnSelect.setOnClickListener {
sqlDB = myHelper.writableDatabase
val cursor: Cursor
cursor = sqlDB.rawQuery("SELECT * FROM groupTBL;", null)
var names = "그룹이름 \r\n ---------- \r\n"
var numbers = "인원 \r\n ---------- \r\n"
while(cursor.moveToNext()) {
names += cursor.getString(0) + "\r\n"
numbers += cursor.getString(1) + "\r\n"
}
editNameResult.setText(names)
editNumberResult.setText(numbers)
cursor.close()
sqlDB.close()
}
}
inner class MyDBHelper(context: Context): SQLiteOpenHelper(context, "groupDB", null, 1) {
override fun onCreate(db: SQLiteDatabase?) {
db!!.execSQL("CREATE TABLE `groupTBL`(`gName` CHAR(20) PRIMARY KEY, `gNumber` INTEGER);")
}
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
db!!.execSQL("DROP TABLE IF EXISTS `groupTBL`;")
onCreate(db)
}
}
}
onCreate() 메서드 밖에 SQLiteOpenHelper 클래스에서 상속받는 내부 클래스를 정의한 후 생성자를 수정
inner class MyDBHelper(context: Context): SQLiteOpenHelper(context, "groupDB", null, 1) {}
super의 두 번째 파라미터에는 새로 생성될 데이터베이스의 파일명을 지정
마지막 파라미터는 데이터베이스 버전으로 처음에는 1을 지정
MyDBHelper 클래스의 onCreate()와 onUpgrade() 메서드를 코딩
override fun onCreate(db: SQLiteDatabase?) {
db!!.execSQL("CREATE TABLE `groupTBL`(`gName` CHAR(20) PRIMARY KEY,
`gNumber` INTEGER);")
}
테이블을 생성하는 SQL문.
onUpgrade()에서 호출되거나 데이터를 입력할 때 혹은 테이블이 없을 때 처음 한 번 호출.
override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) {
db!!.execSQL("DROP TABLE IF EXISTS `groupTBL`;")
onCreate(db)
}
테이블을 삭제하고 새로 생성. 초기화 할 때 호출
초기화 버튼를 클릭했을 때 동작하는 리스너 코딩
myHelper = MyDBHelper(this)
생성자가 실행되어 groupDB 파일이 생성
sqlDB = myHelper.writableDatabase
myHelper.onUpgrade(sqlDB, 1, 2)
sqlDB.close()
groupDB를 쓰기용 데이터베이스로 열고, onUpgrade() 메서드를 호출. groupTBL 테이블이 있으면 삭제한 후 새로 생성. 이후 데이터베이스를 닫음.
onUpgrade()의 두번째 파라미터에는 이전 버전을, 세 번째 파라미터는 새버전을 입력하는데 파라미터를 받은 다음 사용하지 않았으므로 아무 숫자나 넣어도 됨.
입력 버튼를 클릭했을 때 동작하는 리스너 코딩
sqlDB = myHelper.writableDatabase
groupDB를 쓰기용으로 열기
sqlDB.execSQL("INSERT INTO `groupTBL` VALUES ('${editName.text.toString()}'," +
" ${editNumber.text.toString()});")
insert 문을 생생 후 execSQL() 메서드로 실행
조 버튼를 클릭했을 때 동작하는 리스너 코딩
while (cursor.moveToNext()) {
names += cursor.getString(0) + "\r\n"
numbers += cursor.getString(1) + "\r\n"
}
행 데이터의 개수만큼 반복. moveToNext() 메서드는 커서 변수의 다음 행으로 넘어감.
만약 다음행이 없다면 false를 반환하여 while문이 끝남.
getString(열번호)는 현재 커서의 열 번호 데이터 값을 반환하여 문자열 변수에 계속 누적.
0은 0번째 열 (그룹이름 열), 1은 1번째 열(인원).
[ 내용 참고 : IT 학원 강의 ]
'Android Studio' 카테고리의 다른 글
[Android Studio] SQLite 예제 (1) MyDBHelper를 외부 클래스로 작성 (0) | 2024.05.21 |
---|---|
[Android Studio] 구글 지도 (0) | 2024.05.17 |
[Android Studio] 액티비티와 인텐트의 응용 (0) | 2024.05.12 |
[Android Studio] 인텐트 활용한 명화 투표 (0) | 2024.05.11 |
[Android Studio] 액티비티와 인텐트 (0) | 2024.05.10 |