SQL 매퍼 프레임워크 구현과 관련해서 Application 클래스, Executor 클래스, Shop 클래스, SqlMapper 클래스를 작성한다. 


Application 클래스는 JDBC 인터페이스를 사용해서 데이터를 조회한다.

Executor 클래스는 Application 객체를 생성한 다음 view( ) 메소드를 호출한다.

이때 Shop 클래스를 리절트 객체로 사용한다.

SqlMapper 클래스는 Application 클래스의 부모 클래스로 개선이 필요한 소스 코드를 추출해서 메소드로 작성한다.


먼저 Shop 클래스를 작성한 다음 Application 클래스Executor 클래스를 순차적으로 작성한다. 

SqlMapper 클래스는 기능 구현에 따라 단계적으로 작성한다.


1. Shop 클래스 생성 경로 : /chapter01/src/org/mybatis/domain/Shop.java


shopNo;

shopName;

shopLocation;

shopStatus;

2. SHOP 테이블에 정의한 컬럼을 기준으로 프로퍼티를 선언한다. 프로퍼티명은 컬럼명을 낙타 표기 형식에 맞추어 변환한 문자열을 사용한다. 


int shopNo;

String shopName;

String shopLocation;

String shopStatus;

3. 프로퍼티를 선언한 다음 컬럼 타입에 적합한 자바 타입을 프로퍼티 타입으로 선언한다. 컬럼 타입이 숫자 타입인 경우 int 타입 또는 Integer 타입을 프로퍼티 타입으로 선언하고, 문자 타입인 경우 String 타입을 프로퍼티 타입으로 선언한다.


/* 접근 제한자 */

private int shopNo;

private String shopName;

private String shopLocation;

private String shopStatus;


/* 셋터 메소드 */

public void setShopNo(int shopNo){

this.shopNo = shopNo;

}


/* 겟터 메소드 */

public int getShopNo( ){

return this.shopNo;

}

4. 선언한 프로퍼티 값을 직접 변경하지 못하도록 접근 제한자를 지정한 다음 셋터 메소드와 겟터 메소드를 작성한다.


private int shopNo;

private String shopName;

private String shopLocation;

private String shopStatus;


/* 기본 생성자 */

public Shop( ) {


}


/* 생성자 */

public Shop(int shopNo, String shopName, String shopLocation, String shopStatus){

this.shopNo = shopNo;

this.shopName = shopName;

this.shopLocation = shopLocation;

this.shopStatus = shopStatus;

}

5. 두 개의 생성자를 작성한다. 하나는 기본 생성자이고, 다른 하나는 모든 프로퍼티를 인자로 지정한 생상자다.

* 생성자는 클래스명과 이름이 동일하고, 반환 타입이 생략된 메소드를 말한다. 특히 생성자 가운데 인자가 없는 생성자를 기본 생성자라고 한다.


import java.io.Serializable;


public class Shop implements Serializable {


}

6. Serializable 인터페이스를 지정한다.


Application 클래스를 작성한다. JDBC 인터페이스 호출 순서를 따라 작성한 Application 클래스는 데이터베이스로부터 조건에 맞는 데이터를 한 건 조회한다. Application 클래스는 단계적인 리팩토링 작업을 통해서 점진적으로 작성한다. Application 클래스를 작성할 때 Shop 클래스를 리절트 객체로 사용한다.


7. Application 클래스 생성 경로 : /chapter01/src/step0/Application.java


import java.sql.SQLException;

import java.util.List;


public class Application {

public void view(List<Object> parameters) throws SQLException {

try {

// JDBC 드라이버 로딩

Class.forName("oracle.jdbc.driver.OracleDriver");

} catch (ClassNotFoundException e) {

e.printStackTrace( );

}

}

}

8. view( ) 메소드를 정의한다. view( ) 메소드에 Class 클래스의 forName( ) 메소드를 사용해서 JDBC 드라이버를 로딩하는 소스 코드를 작성한다. forName( ) 메소드를 호출할 때 패키지 경로를 포함한 (오라클 데이터베이스의) JDBC 드라이버 클래스를 인자로 전달한다. 빌드 경로에서 JDBC 드라이버 클래스를 찾지 못하면 ClassNotFoundException 예외가 발생한다. 이런 경우에 try ~ catch 문을 사용해서 예외를 처리한다. 


import java.sql.Connection;

import java.sql.DriverManager;


public class Application {

public void view(List<Object> parameters) throws SQLException {

Connection connection = null;


try {

// JDBC 드라이버 로딩

Class.forName("oracle.jdbc.driver.OracleDriver");


// 데이터베이스 연결

connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE", "mybatis", "mybatis");

} catch (ClassNotFoundException e) {

throw new RuntimeException(e);

}

}

}

9. JDBC 드라이버를 로딩한 다음 DriverManager 클래스의 getConnection( ) 메소드를 호출하면, Connection 객체를 반환받을 수 있다. getConnection( ) 메소드를 호출할 때 데이터베이스 연결 URL, 계정, 비밀번호를 인자로 지정한다.


import java.sql.PreparedStatement;


public class Application {

public void view(List<Object> parameters) throws SQLException {

Connection connection = null;

PreparedStatement preparedStatement = null;


try {

...


// 데이터베이스 연결

connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE", "mybatis", "mybatis");


// 쿼리문 처리 객체 생성

preparedStatement = connection.prepareStatement(

"SELECT SHOP_NO, SHOP_NAME, SHOP_LOCATION, SHOP_STATUS "

 + "FROM SHOP WHERE SHOP_NO = ? AND SHOP_STATUS = ?");


// 파라미터 바인딩

preparedStatement.setInt(1, (Integer) parameters.get(0));

preparedStatement.setString(2, String.valueOf(parameters.get(1));

} catch (ClassNotFoundException e) {

throw new RuntimeException(e);

}

}

}

10. 반환된 Connection 객체의 preparedStatement( ) 메소드를 호출하면, PreparedStatement 객체를 반환받을 수 있다. PreparedStatement에서 제공하는 다양한 셋터 메소드를 사용해서 매개 변수를 지정한 쿼리문에 파라미터를 바인딩할 수 있다. 매개 변수의 컬럼 타입이 숫자 타입인 경우 setInt( ) 메소드를 사용하고, 문자 타입인 경우 setString( ) 메소드를 사용한다. 셋터 메소드의 인자로 매개 변수 순번과 파라미터를 전달한다.


import java.sql.ResultSet;


public class Application {

public void view(List<Object> parameters) throws SQLException {

...

PreparedStatement preparedStatement = null;

ResultSet resultSet = null;


try {

...


// 파라미터 바인딩

preparedStatement.setInt(1, (Integer) parameters.get(0));

preparedStatement.setString(2, String.valueOf(parameters.get(1));


// 쿼리문 실행 및 결과 반환

resultSet = preparedStatement.executeQuery( );

} catch (ClassNotFoundException e) {

throw new RuntimeException(e);

}

}

}

11. PreparedStatement 객체의 executeQuery( ) 메소드를 호출하면, 조회 쿼리문을 실행한 다음 결과를 담은 ResultSet 객체를 반환받을 수 있다.


import org.mybatis.domain.Shop;


public class Application {

public Shop view(List<Object> parameters) throws SQLException {

...

ResultSet resultSet = null;

Shop shop = null;


try {

...


// 쿼리문 실행 및 결과 반환

resultSet = preparedStatement.executeQuery( );


// 결과 처리

if(resultSet.next()){

shop = new Shop( );


shop.setShopNo(resultSet.getInt("SHOP_NO"));

shop.setShopName(resultSet.getString("SHOP_NAME"));

shop.setShopLocation(resultSet.getString("SHOP_LOCATION"));

shop.setShopStatus(resultSet.getString("SHOP_STATUS"));

}

} catch (ClassNotFoundException e) {

throw new RuntimeException(e);

}


return shop;

}

}

12. 조회 결과는 ResultSet 객체에 행과 열 형태로 담겨 반환된다. ResultSet 객체의 next( ) 메소드를 호출하면, 각 행에 순차적으로 접근할 수 있다. 행에 존재하는 각 열의 값은 다양한 겟터 메소드를 사용해서 가져올 수 있다. 열의 값이 숫자 타입인 경우 getInt( ) 메소드를 사용하고, 문자 타입인 경우 getString( ) 메소드를 사용한다. 겟터 메소드의 인자로 컬럼명을 지정한다.


public class Application {

public Shop view(List<Object> parameters) throws SQLException {

...


try {

...

}

} catch (ClassNotFoundException e) {

throw new RuntimeException(e);

} finally {

// 자원 및 데이터베이스 연결 해제

if(resultSet!=null){

resultSet.close();

}

if(preparedStatement!=null){

preparedStatement.close();

}

if(connection!=null){

connection.close();

}

}


return shop;

}

}

13. try ~ catch 문에 finally 문을 추가한 다음 사용한 자원 및 데이터베이스 연결을 해제한다. 객체 생성 순서의 역순으로 자원 및 데이터베이스 연결 객체의 close( ) 메소드를 호출한다.


Executor 클래스를 작성한다. Executor 클래스는 main( ) 메소드 실행을 통해서 Application 객체를 생성한 다음 view( ) 메소드를 호출한다.


14. Executor 클래스 생성 경로 : /chapter01/src/step0/Executor.java


import java.util.ArrayList;

import java.util.List;


public class Executor {

public static void main(String[] args){

// 파라미터 객체 생성 및 파라미터 등록

List<Object> parameters = new ArrayList<Object>( );

parameters.add(1);

parameters.add("Y");

}

}

15. main( ) 메소드를 작성한다. main( ) 메소드에 Application 객체의 view( ) 메소드를 호출할 때 필요한 파라미터 객체를 준비한다.


import org.mybatis.domain.Shop;


public class Executor {

public static void main(String[] args){

// 파라미터 객체 생성 및 파라미터 등록

List<Object> parameters = new ArrayList<Object>( );

parameters.add(1);

parameters.add("Y");


// 조회 쿼리문 실행 및 결과 반환

Application application = new Application();

try {

Shop shop = application.view(parameters);

} catch (SQLException e) {

e.printStackTrace();

}


}

}

16. Application 객체를 생성한 다음 view( ) 메소드를 호출한다. 준비한 파라미터 객체를 인자로 전달한다. Application 객체의 view( ) 메소드를 호출할 때 에러가 발생할 수 있다. try ~ catch 문을 사용해서 예외를 처리한다.


Application 클래스는 JDBC 인터페이스 호출 순서에 맞추어 작성한 전형적인 JDBC 인터페이스 호출 순서에 맞추어 작성한 전형적인 JDBC 프로그래밍이다. Application 클래스는 Executor 클래스의 main( ) 메소드 호출을 통해서 실행된다.


JDBC 프로그래밍 단점을 고스란히 가진 Application 클래스를 개선하는 데 필요한 SqlMapper 클래스를 작성한다. SqlMapper 클래스를 완성하면, Application 클래스는 좀 더 간결하고 유연한 구조를 가질 수 있다. 


SQLMapper 클래스에 구현할 기능

1. 중복된 기능 추출

2. 외부 파일 정의

3. 인자와 결과를 자동 처리

4. 단순한 실행 메소드 정의


자바 애플리케이션 개발 환경

1. 데이터베이스 설치

① 오라클 데이터베이스 설치

② 사용자 계정 생성

③ 테이블 생성

2. 자바 설치

① 자바 설치 및 설정

3. 라이브러리 다운로드

① 마이바티스 라이브러리 다운로드

② JDBC 라이브러리 다운로드

4. 이클립스 설치

① 이클립스 설치 및 설정

5. 자바 프로젝트 생성

① 자바 프로젝트 생성

② 라이브러리 복사 및 빌드 경로 설정

③ 인코딩 설정


1. 데이터베이스 설치

① 오라클 데이터베이스 설치

http://minimelody.tistory.com/146와 동일하므로 PASS~


② 사용자 계정 생성

CREATE USER mybatis IDENTIFIED BY mybatis;

GRANT CONNECT, RESOURCE, DBA TO mybatis;

관리자 계정으로 접속하고 다음 명령어를 순서대로 실행하면, 사용자 계정을 생성하고 권한을 부여할 수 있다.


③ 테이블 생성

SHOP 테이블

컬럼명 

타입 

길이 

구분 

설명 

SHOP_NO

NUMBER 

 

기본키 

가게 번호 

SHOP_NAME

VARCHAR2 

100 

 

가게 이름 

SHOP_LOCATION 

CLOB 

 

 

가게 주소 

SHOP_STATUS 

VARCHAR2 

 

가게 상태 


TOY 테이블

컬럼명 

타입 

길이 

구분 

설명 

TOY_NO 

NUMBER 

 

기본키 

장난감 번호 

TOY_NAME 

VARCHAR2 

100 

 

장난감 이름 

TOY_PRICE 

NUMBER 

 

 

장난감 가격 

SHOP_NO 

NUMBER 

 

참조키 

장난감을 보유한 가게 번호 


/* 가게 테이블 생성 */

CREATE TABLE SHOP (

SHOP_NO NUMBER NOT NULL ENABLE,

SHOP_NAME VARCHAR2(100 BYTE),

SHOP_LOCATION CLOB,

SHOP_STATUS VARCHAR2(1 BYTE),

CONSTRAINT SHOP_PK PRIMARY KEY (SHOP_NO)

);


/* 가게 테이블 데이터 등록 */

INSERT INTO SHOP VALUES (1, 'Toy Store', 'A Tower Seocho dong', 'Y');

INSERT INTO SHOP VALUES (2, 'Play Store', 'B Tower Seocho dong', 'Y');

INSERT INTO SHOP VALUES (3, 'Mom Store', 'C Tower Seocho dong', 'Y');


/* 장난감 테이블 생성 */

CREATE TABLE TOY (

TOY_NO NUMBER NOT NULL ENABLE,

TOY_NAME VARCHAR2(100 BYTE),

TOY_PRICE NUMBER,

SHOP_NO NUMBER NOT NULL ENABLE,

CONSTRAINT TOY_PK PRIMARY KEY (TOY_NO)

);


/* 장난감 테이블 데이터 등록 */

INSERT INTO TOY VALUES (1, 'Lego (Model-A100)', 30000, 1);

INSERT INTO TOY VALUES (2, 'Lego (Model-A200)', 60000, 1);

INSERT INTO TOY VALUES (3, 'Lego (Model-A300)', 90000, 1);


COMMIT;


/* 가게 번호 시퀀스 생성 */

CREATE SEQUENCE SEQ_SHOP_NO INCREMENT BY 1 START WITH 4;

위와 같이 작성한 SQL 스크립트를 실행하고


SELECT * FROM SHOP;

SHOP 테이블과


SELECT * FROM TOY;

TOY 테이블에 등록한 초기 데이터를 확인할 수 있다


오라클 데이터베이스를 설치하면, 웹 애플리케이션에서 오라클 데이터베이스를 관리할 수 있는 웹 관리 콘솔이 함께 설치된다. 

관리자(SYSTEM) 계정에서

SELECT dbms_xdb.gethttpport FROM dual;

설치된 웹 관리 콘솔은 다음과 같이 8080 포트 번호를 기본 포트 번호로 사용한다. 8080 포트 번호는 아파치 톰캣에서 사용하는 기본 포트 번호와 동일한 포트 번호다. 동일한 포트 번호를 사용하면, 포트 번호 충돌로 인해 웹 서비스 실행이 안 되는 문제가 발생한다.


BEGIN

dbms_xdb.sethttpport(8081);

END;

다음 명령어를 실행하여 웹 관리 콘솔의 포트 번호를 8080에서 8081로 변경한다. 


변경한 웹 관리 콘솔의 포트 번호를 반영하기 위해서 반드시 오라클 데이터 베이스를 다시 시작해야 한다. 우선 오라클 데이터베이스를 정지하려면, 윈도우 메뉴에서 Oracle Database 11g Express Edition - Stop Database를 선택한다. 

오라클 데이터베이스를 다시 시작하려면, 윈도우 메뉴에서 Oracle Database 11g Express Edition - Start Database를 선택한다.



2. 자바 설치

① 자바 설치 및 설정

자바 설치 버전은 마이바티스 프로그래밍 개발 환경에 전반적인 영향을 미친다. 자바 설치 버전을 결정할 때 '이클립스 설치 버전, 아파치 톰캣 설치 버전', '스프링 라이브러리 버전', '마이바티스 라이브러리 버전', '마이바티스-스프링 라이브러리 버전', '기타 라이브러리 버전' 을 함께 고려해야 한다.


여기서는

이클립스 - 4.6 버전

아파치 톰캣 - 8.0.36 버전

마이바티스 라이브러리 - 3.4.1 버전

스프링 라이브러리 - 4.3.1 버전

마이바티스 - 스프링 연동 라이브러리 - 1.3.0 버전


이클립스 4.6 버전과 아파치 톰캣 8.0.36 버전은 자바 7 이상 버전이 필요하고, 마이바티스 3.4.1 버전과 스프링 4.3.1 버전은 자바 6 이상 버전이 필요하다. 마이바티스 - 스프링 연동 1.3.0 버전은 마이바티스 버전에 따라 자바 6이상 버전이 필요하다. 따라서 자바 7 버전 이상을 설치해야 한다.


http://minimelody.tistory.com/150에서 JDK 8 버전 설치 완료!



3. 라이브러리 다운로드

① 마이바티스 라이브러리 다운로드

https://github.com/mybatis/mybatis-3/releases에서 마이바티스 라이브러리를 다운로드한다. 마이바티스 3.4.1 버전을 사용한다.

* 마이바티스 라이브러리 3.2.0 이하 버전까지는 자바 5 버전에서 사용 가능하다. 반면에 마이바티스 라이브러리 3.2.0 이상 버전은 자바 6 이상 버전을 사용해야 한다.


다운로드한 mybatis-3.4.1.zip 압축 파일을 해제하면   mybatis-3.4.1.jar  파일이 있다.


② JDBC 라이브러리 다운로드

www.oracle.com/technetwork/database/features/jdbc/index-091264.html이나


오라클 데이터베이스가 이미 설치되어 있다면, JDBC 라이브러리를 별도로 다운로드 하지 않고 

C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib 에서   ojdbc6.jar파일을 찾아 사용할 수 있다.


마이바티스는 3.3.0 버전부터 기본 프록시 도구로 Javassist를 사용한다. 만일 다른 프록시 도구를 사용할 필요가 있는 경우 라이브러리를 추가로 다운로드해야 한다. 예를 들어 Cglib 프록시를 사용하는 경우 다음 URL 주소에서 CGLIB 라이브러리와 ASM 라이브러리를 다운로드할 수 있다. 


CGLIB 3.2.4 : http://mvnrepository.com/artifact/cglib/cglib/3.2.4 -   cglib-3.2.4.jar

ASM 5.1 : http://mvnrepository.com/artifact/org.ow2.asm/asm/5.1 -   asm-5.1.jar


아파치 Log4j2 라이브러리는 https://logging.apache.org/log4j/2.x/download.html에서 다운로드할 수 있다.


apache-log4j-2.11.1-bin.zip 압축 파일을 해제하면, 

log4j-api-2.11.1.jar

log4j-core-2.11.1.jar

log4j-slf4j-impl-2.11.1.jar

가 자바 프로젝트에서 사용하는 라이브러리이다.



4. 이클립스 설치

① 이클립스 설치 및 설정

이클립스 버전 

 자바 버전

4.4 이상 버전 

1.7 이상 버전 

4.x ~ 4.3 이하 버전 

1.6 이상 버전 

3.x 버전 

1.5 이상 버전 

2.x 버전 

1.4 이상 버전 


http://www.eclipse.org/downloads/packages/release/neon/3에서 이클립스 4.6버전을 다운로드한다. 


다운로드한 eclipse-jee-neon-3-win32-x86_64.zip 압축 파일은 별도로 설치 과정 없이 압축 파일을 해제한 다음 바로 실행할 수 있다.

C:\Program Files\에 압축 해제한 eclipse를 위치한다. eclipse 내에 eclipse.exe 파일을 실행하면 이클립스가 실행된다.


처음 이클립스를 실행하면, Workspace Launcher 대화상자가 나타난다. 워크스페이스는 이클립스 설정 정보와 소스 코드를 저장한 공간을 말한다. Workspace Launcher 대화상자를 살펴보면, 사용자 계정 하위 경로가 워크스페이스 저장 경로로 지정된 것을 볼 수 있다. 워크스페이스 저장 경로를 변경할 필요가 있다면, Browser.. 버튼을 눌러 원하는 경로를 지정한 다음 OK 버튼을 누른다.



5. 자바 프로젝트 생성

① 자바 프로젝트 생성

이클립스 상단 메뉴바에서 File - New - Project 메뉴를 선택한다. New 대화상자가 나타나면, Java Project 항목을 선택한 다음 Next 버튼을 누른다.


New Java Project 대화상자가 나타나면, Project name 입력 항목에 프로젝트명을 입력한 다음 Finish 버튼을 누른다.


자바 프로젝트 생성을 완료하면 Package Explorer 뷰에서 자바 프로젝트를 확인할 수 있다.


② 라이브러리 복사 및 빌드 경로 설정

/chapter01/lib 디렉토리를 생성한 다음 앞서 다운로드한 라이브러리를 복사한다.


자바 프로젝트에 복사한 라이브러리를 빌드 경로에 등록한다. 자바 프로젝트를 선택한 다음 마우스 우측 버튼을 누른다. 항목 중 Properties 메뉴를 선택하면, Properties 대화상자가 나타난다. Properties 대화상자 좌측 목록 중 Java Build Path 항목을 선택하고 Libraries 탭을 선택한 다음 Add JARs... 버튼을 누르면, JAR Select 대화상자가 열린다. /chapter01/lib 디렉토리에 포함된 모든 라이브러리를 선택한 다음 OK 버튼을 눌러 빌드 경로 설정을 완료한다.


빌드 경로에 라이브러리를 등록하면, Referenced Libraries 목록에서 등록한 라이브러리를 확인할 수 있다.


③ 인코딩 설정

자바 프로젝트에서 소스 코드를 작성할 때 한글이 깨지는 것을 방지하기 위해서 인코딩을 UTF-8로 설정한다. 인코딩 설정은 Properties에서 지정할 수 있다. Properties 대화상자 좌측 목록 중 Resource 항목을 선택하면, 우측 영역이 바뀐다. 우측 Text file Encoding 영역에서 UTF-8을 선택한 다음 OK 버튼을 눌러 인코딩 설정을 완료한다.

+ Recent posts