데이터베이스를 만들고 리스트 화면, 문제 만들기 화면, 문제 풀기 화면에서 데이터를 조회하고 저장하는 기능을 구현하였다.
데이터베이스와 테이블을 만들고, 데이터베이스를 이용할 수 있는 메소드를 정의한 클래스 QuestionDatabase.java를 만들었다.
package org.techtown.qself;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import androidx.annotation.Nullable;
public class QuestionDatabase {
private static final String TAG = "QuestionDatabase";
// 싱글톤 인스턴스
private static QuestionDatabase database;
// 테이블 이름
public static String TABLE_QUESTION = "QUESTION";
// 데이터베이스 이름
public static String DATABSE_NAME = "question.db";
// 데이터베이스 버전
public static int DATABASE_VERSION = 1;
private DatabaseHelper dbHelper;
private SQLiteDatabase db;
private Context context;
private QuestionDatabase(Context context){
this.context = context;
}
// 싱글톤 인스턴스
public static QuestionDatabase getInstance(Context context){
if(database == null)
database = new QuestionDatabase(context);
return database;
}
// 데이터베이스 열기
public boolean open(){
println("Database Open.");
dbHelper = new DatabaseHelper(context);
db = dbHelper.getWritableDatabase();
return true;
}
// 데이터베이스 닫기
public void close(){
println("Database Close.");
db.close();
database = null;
}
// 쿼리문 실행
public Cursor rawQuery(String SQL){
Cursor cursor = null;
try{
cursor = db.rawQuery(SQL, null);
println("Execute Query.");
}catch (Exception ex){
Log.e(TAG, "Exception in executeQuery", ex);
}
return cursor;
}
// SQL문 실행
public boolean execSQL(String SQL){
try{
Log.d(TAG,"SQL : " + SQL);
db.execSQL(SQL);
println("Execute SQL");
}catch (Exception ex){
Log.e(TAG,"Exception in executeQuery", ex);
return false;
}
return true;
}
// 데이터베이스 헬퍼 클래스
private class DatabaseHelper extends SQLiteOpenHelper{
public DatabaseHelper(Context context){
super(context, DATABSE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// 이미 존재하는 테이블 DROP
String DROP_SQL = "drop table [" + TABLE_QUESTION + "]";
try{
db.execSQL(DROP_SQL);
println("Drop Table.");
}catch (Exception ex){
Log.e(TAG, "Exception in DROP_SQL", ex);
}
// 테이블 생성
String CREAT_SQL = "create table " + TABLE_QUESTION + "("
+" _id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "
+" TITLE TEXT DEFAULT '', "
+" QUESTION TEXT DEFAULT '', "
+" ANSWER TEXT DEFAULT '' "
+")";
try{
db.execSQL(CREAT_SQL);
println("Create Table.");
}catch (Exception ex){
Log.e(TAG,"Exception in CREATE_SQL", ex);
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
println("Upgrading Database from version : " + oldVersion + "to " + newVersion + ".");
}
@Override
public void onOpen(SQLiteDatabase db) {
println("opened Database : " + DATABSE_NAME + ".");
}
}
private void println(String msg){
Log.d(TAG, msg);
}
}
싱글톤 인스턴스로 클래스를 정의하였다.
public class QuestionDatabase {
private static final String TAG = "QuestionDatabase";
// 싱글톤 인스턴스
private static QuestionDatabase database;
// 테이블 이름
public static String TABLE_QUESTION = "QUESTION";
// 데이터베이스 이름
public static String DATABSE_NAME = "question.db";
// 데이터베이스 버전
public static int DATABASE_VERSION = 1;
private DatabaseHelper dbHelper;
private SQLiteDatabase db;
private Context context;
private QuestionDatabase(Context context){
this.context = context;
}
// 싱글톤 인스턴스
public static QuestionDatabase getInstance(Context context){
if(database == null)
database = new QuestionDatabase(context);
return database;
}
데이터베이스 헬퍼 클래스를 사용하여 데이터베이스와 테이블을 만들었다.
데이터베이스의 이름은 "question.db",
테이블의 이름은 "QUESTION"으로 하였고,
테이블의 속성은 _id, TITLE, QUESTION, ANSWER로 정의하였다.
// 데이터베이스 헬퍼 클래스
private class DatabaseHelper extends SQLiteOpenHelper{
public DatabaseHelper(Context context){
super(context, DATABSE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// 이미 존재하는 테이블 DROP
String DROP_SQL = "drop table [" + TABLE_QUESTION + "]";
try{
db.execSQL(DROP_SQL);
println("Drop Table.");
}catch (Exception ex){
Log.e(TAG, "Exception in DROP_SQL", ex);
}
// 테이블 생성
String CREAT_SQL = "create table " + TABLE_QUESTION + "("
+" _id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "
+" TITLE TEXT DEFAULT '', "
+" QUESTION TEXT DEFAULT '', "
+" ANSWER TEXT DEFAULT '' "
+")";
try{
db.execSQL(CREAT_SQL);
println("Create Table.");
}catch (Exception ex){
Log.e(TAG,"Exception in CREATE_SQL", ex);
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
println("Upgrading Database from version : " + oldVersion + "to " + newVersion + ".");
}
@Override
public void onOpen(SQLiteDatabase db) {
println("opened Database : " + DATABSE_NAME + ".");
}
}
마지막으로 데이터베이스를 열고 닫는 메소드, 쿼리와 SQL문을 실행하는 메소드를 정의하였다.
// 데이터베이스 열기
public boolean open(){
println("Database Open.");
dbHelper = new DatabaseHelper(context);
db = dbHelper.getWritableDatabase();
return true;
}
// 데이터베이스 닫기
public void close(){
println("Database Close.");
db.close();
database = null;
}
// 쿼리문 실행
public Cursor rawQuery(String SQL){
Cursor cursor = null;
try{
cursor = db.rawQuery(SQL, null);
println("Execute Query.");
}catch (Exception ex){
Log.e(TAG, "Exception in executeQuery", ex);
}
return cursor;
}
// SQL문 실행
public boolean execSQL(String SQL){
try{
Log.d(TAG,"SQL : " + SQL);
db.execSQL(SQL);
println("Execute SQL");
}catch (Exception ex){
Log.e(TAG,"Exception in executeQuery", ex);
return false;
}
return true;
}
MainActivity.java에 실행 시 데이터베이스를 열고, 종료 시 데이터베이스를 닫는 코드를 추가하였다.
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
public static final int REQUEST_CODE_MAKE = 101;
// 데이터베이스 인스턴스
public static QuestionDatabase mDatabase = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 데이터베이스 열기
openDatabase();
.
.
.
// 종료 시 데이터베이스 닫기.
@Override
protected void onDestroy() {
super.onDestroy();
if(mDatabase != null){
mDatabase.close();
mDatabase = null;
}
}
// 데이터베이스를 여는 함수
public void openDatabase() {
if(mDatabase != null){
mDatabase.close();
mDatabase = null;
}
mDatabase = QuestionDatabase.getInstance(this);
boolean isOpen = mDatabase.open();
if(isOpen){
Log.d(TAG, "Question database is open.");
}else{
Log.d(TAG, "Question database is not open.");
}
}
}
문제의 목록을 보여주는 ListActivity.java와 SolveActivity.java에 데이터베이스에서 데이터를 가져오고, 리사이클러 뷰에 가져온 데이터를 추가하도록 만들었다.
public class ListActivity extends AppCompatActivity {
RecyclerView recyclerView;
QuestionAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
recyclerView = findViewById(R.id.RecyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(layoutManager);
adapter = new QuestionAdapter();
// 리사이클러뷰에 문제 추가
loadQuestionListData();
.
.
.
// 리사이클러뷰에 문제 추가 메소드
public void loadQuestionListData() {
int recordCount = 0;
String sql = "select _id, TITLE, QUESTION, ANSWER FROM " + QuestionDatabase.TABLE_QUESTION + " order by _id ASC";
QuestionDatabase database =QuestionDatabase.getInstance(this);
if(database != null){
Cursor cursor = database.rawQuery(sql);
recordCount = cursor.getCount();
for(int i = 0; i < recordCount; i++){
cursor.moveToNext();
int _id = cursor.getInt(0);
String Title = cursor.getString(1);
String Question = cursor.getString(2);
String Answer = cursor.getString(3);
adapter.addItem(new Question(_id, Title, Question, Answer));
}
cursor.close();
adapter.notifyDataSetChanged();
}
}
}
public class SolveActivity extends AppCompatActivity {
public static final int REQUEST_CODE_SOLVE = 102;
RecyclerView recyclerView;
QuestionAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_solve);
recyclerView = findViewById(R.id.RecyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(layoutManager);
adapter = new QuestionAdapter();
// 리사이클러뷰에 문제 추가
loadQuestionListData();
.
.
.
public void loadQuestionListData() {
int recordCount = 0;
String sql = "select _id, TITLE, QUESTION, ANSWER FROM " + QuestionDatabase.TABLE_QUESTION + " order by _id ASC";
QuestionDatabase database =QuestionDatabase.getInstance(this);
if(database != null){
Cursor cursor = database.rawQuery(sql);
recordCount = cursor.getCount();
for(int i = 0; i < recordCount; i++){
cursor.moveToNext();
int _id = cursor.getInt(0);
String Title = cursor.getString(1);
String Question = cursor.getString(2);
String Answer = cursor.getString(3);
adapter.addItem(new Question(_id, Title, Question, Answer));
}
cursor.close();
adapter.notifyDataSetChanged();
}
}
}
MakeQuestion.java에 입력된 데이터로 문제를 만들어 데이터베이스에 저장하는 코드를 추가하였다.
public class MakeActivity extends AppCompatActivity {
EditText editTextTitle;
EditText editTextQuestion;
EditText editTextAnswer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_make);
editTextTitle = findViewById(R.id.editTextTitle);
editTextQuestion = findViewById(R.id.editTextQuestion);
editTextAnswer = findViewById(R.id.editTextAnswer);
Button buttonMakeQuestion = findViewById(R.id.buttonMakeQuestion);
buttonMakeQuestion.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 데이터베이스에 문제 추가
addQuestion();
.
.
.
// 데이터베이스에 문제 추가 메소드
private void addQuestion() {
String title = editTextTitle.getText().toString();
String question = editTextQuestion.getText().toString();
String answer = editTextAnswer.getText().toString();
String sql = "insert into " + QuestionDatabase.TABLE_QUESTION +
"(TITLE, QUESTION, ANSWER) values(" +
"'" + title + "', " +
"'" + question + "', " +
"'" + answer + "')";
QuestionDatabase database = QuestionDatabase.getInstance(this);
database.execSQL(sql);
}
}