티스토리 뷰

학교/졸업작품

SQL 조작 클래스의 템플릿화

사탕맛커피 2011. 9. 3. 23:03

기존 코드에서 SQL조작 관련 코드를 Activity내부에서 빼 내에 따로 클래스를 생성하여 관리하도록 변경하였다. 이로써 각 클래스의 역할이 좀 더 명확해지게 되었다.

사용하는 SQL Table은 Article, Photo, Message, C2DM과 같은 데이터를 관리한다.

각각 공통으로 가지는 메소드가 있기 때문에 이를 명확하게 하기 위해 다음과 같은 Base클래스를 작성하였다.

 
클라이언트

public abstract class SQLiteTable<T> {
	protected Context mContext;
	protected String QTE = "'";
	
	public SQLiteTable(Context context){
		mContext = context;
	}
	/** SQLite DB에 추가 */
	public abstract int insert(T item);
	/** SQLite DB에서 삭제 */
	public abstract boolean delete(T item);
	/** SQLite DB를 업데이트 */
	public abstract boolean update(T item);
	
	public abstract int getLastId();
	public abstract T getItem(int id);
	public abstract ArrayList<T> getAllItems();
	
	/** Cursor 객체에서 데이터를 가져온다. 
	 * @param	c : 데이터를 가져 올 커서
	 */
	protected abstract T getFromCursor(Cursor c);
}

서버
public abstract class SQLTable<T> {
	protected ResultSet rs;
	protected PreparedStatement psmt;
	protected Connection jdbcConnection;
	
	/** 기본 생성자 (Connection 변수가 필요)*/
	public SQLTable(Connection jdbcConnection) {
		this.jdbcConnection = jdbcConnection;
	}
	
	/** DB에 Item 추가 */
	public abstract int insert(T item);
	/** DB에서 Item 삭제 */
	public abstract boolean delete(T item);
	/** DB에 Item 업데이트 */
	public abstract boolean update(T item);
	/** tuple id로 item을 가져온다. */
	public abstract T getItem(int id);
	/** 모든 아이템을 가져온다. */
	public abstract ArrayList<T> getAllItems();
	/** ResultSet으로분터 내용을 가져온다. */
	protected abstract T getFromResultSet(ResultSet rs);
	
	/** Database관련 변수를 닫는다. */
	protected void closeStatement(){
		try{
			if (rs != null) rs.close();
		}catch (SQLException e){
			e.printStackTrace();
		}
		try{
			if (psmt != null) psmt.close();
		}catch (SQLException e){
			e.printStackTrace();
		}
	}
	/** ResultSet의 tuple수를 얻는다. (MySQL JDBC에는 getCount메소드가 없음)*/
	protected int getResultSetCount(ResultSet rs){
		try{
			if (rs == null || (rs.first() == false)) return 0;
			int currentRow = rs.getRow(); 	// 현재 위치 저장
			rs.last(); 						// 마지막 줄로 이동하여 행 수를 알아온다. (행 : 1,2,3,.....,n)
			int rsCount = rs.getRow();
			rs.absolute(currentRow);		// 원래 위치로 복원
			return rsCount;
		}
		catch (SQLException e){
			e.printStackTrace();
			return -1;
		}
	}
}

기본으로 insert, delete, update의 메소드가 필요하고, tuple을 가져오는 getItem, getAllItems, 커서(ResultSet)에서 데이터를 가져오는 getFromCursor 메소드를 선언한다.
Base클래스는 abstract 키워드로 선언되는데, 몇몇 메소드는 Body를 가지고 있기 때문에 interface 키워드를 사용할 수 없다.

abstract와 interface의 차이를 명확하게 하기 위해 구분 표를 만들었다.

 

 

abstract

interface

1. 형태 Prototype만 있거나, Body까지 있는 메소드를 혼용 가능 메소드를 Prototype으로만 선언
2. 사용 키워드 클래스 시작: abstract
상속: extends
클래스 시작: interface
상속: implements
3. 다중상속 가능 불가

가능

 

간단하게, 클래스 추상화가 일반클래스 > abstract > interface 순으로 생각할 수 있겠다.

그런데, 이 클래스를 상속받아 새로 클래스를 만들면서 기본으로 선언한 메소드들을 사용하지 않는 경우가 있다. 예를 들어, 테이블을 생성하는 클래스를 만들었는데, 위에 선언한 모든 메소드를 사용하지 않는다.

 

/** 사용하지 않음 */ @Deprecated @Override
protected Object getFromResultSet(ResultSet rs) {return null;}
// 구현하지 않음

메소드 앞에 @Deprecated를 선언하면 이 메소드는 조만간 폐기 될 것을 알려주는 역할을 한다. 메소드 이름에는 취소선이 생기고, Code Assist의 아이콘에 오른쪽 사선이 생긴다. 사실 사용하는 목적이 약간 다르긴 하지만 혹시 모를 잘못된 사용을 방지하기 위한 조치다. 물론 메소드 호출은 가능하지만 정상적은 동작은 보장하지 않는다.

'학교 > 졸업작품' 카테고리의 다른 글

최종 보고서  (0) 2011.09.23
7,8월 중간 보고서  (0) 2011.09.01
코드 리팩토링  (0) 2011.08.30
다른 액티비티로 메시지 전송 (2)  (0) 2011.08.23
서버 클라이언트 통신시 데이터 전달 및 기타...  (0) 2011.08.22
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
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 31
글 보관함