BLOG main image
분류 전체보기 (313)
교육 (13)
NEIS (6)
Edufine (0)
Programmer (5)
Android Programming (1)
Internet W3 (18)
JAVA Programming (9)
JSP/Servlet (1)
Framework (7)
Spring For Beginner (4)
eGovFrame (10)
MEAN Stack (2)
NodeJS (5)
SublimeText (30)
SublimeText_Tips (18)
Eclipse (16)
JavaScript (8)
jQuery (12)
jQuery_tips (1)
Ajax (3)
DWR(Direct Web Remote) (4)
JSON(JS Object Notation) (4)
Oracle (2)
MySQL (28)
OS (16)
Download (3)
Life (10)
Favorit Site (1)
Books (2)
Healthy (1)
Stocks (1)
HTML5/CSS (1)
Python (4)
Security (7)
CISSP (0)
Ruby On Rails (5)
일기장 (0)
영어 교과서(중2) (3)
알고리즘 (0)
Go Lang (3)
VB 2010 (12)
C# (1)
정보보안기사(네트워크보안) (0)
업무 활용 엑셀 (11)
틈틈이 활용팁 (14)
하루 하루 살아가며 ……. (2)
기술 (1)
파이썬 & 데이터분석 (1)
Visitors up to today!
Today hit, Yesterday hit
daisy rss
tistory 티스토리 가입하기!
2015. 7. 20. 11:30

전자정부표준프레임워크를 잘 정리한 요약 자료...


전자정부 표준프레임워크 개요 요약 (1-1) http://tobewiseys.tistory.com/52

전자정부 표준프레임워크 개요 요약 (1-2) http://tobewiseys.tistory.com/63


- 교육 (실행환경을 중심으로 ...)


실행환경:

화면처리, 업무처리, 데이터처리, 연계통합, 공통기반

AOP, IoC/DI 에 대한 설명..

무지하게 졸린다. 열심히 읽는다. 잘 읽기는 하지만 듣기가 힘들다.


실습

lab204-dataaccess


xxx.sql 파일을 열고 type, name, database 를 지정하고 마우스 오른쪽 버튼을 눌러 'Execute All 을 선택'




----------------------------------------------------------

 

실습환경 구성

- lab204-dataaccess 프로젝트 import

- maven repository 설정 및 dependency library 맞춤


Step 1. 구동 환경 설정


1) Hsqldb 초기화 스크립트

. /lab204-dataaccess/src/test/resources/META-INF/testdata/sample_schema_hsql.sql 를 확인한다.

현 실습 프로젝트에서는 편의상 매 테스트 케이스 재실행 시 관련 table 을 drop/create 하고 있음.

2) dataSource 설정

. /lab204-dataaccess/src/test/resources/META-INF/spring/context-common.xml 에 context:property-placeholder 설정을 추가한다.

/**************************************************************************************/

<context:property-placeholder

location="classpath:/META-INF/spring/jdbc.properties" />

/**************************************************************************************/


. /lab204-dataaccess/src/test/resources/META-INF/spring/context-datasource.xml 를 설정한다.

/**************************************************************************************/

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"

destroy-method="close">

<property name="driverClassName" value="${driver}" />

<property name="url" value="${dburl}" />

<property name="username" value="${username}" />

<property name="password" value="${password}" />

<property name="defaultAutoCommit" value="false" />

<property name="poolPreparedStatements" value="true" />

</bean>

/**************************************************************************************/


. /lab204-dataaccess/src/test/resources/META-INF/spring/jdbc.properties 를 작성한다.

/**************************************************************************************/

driver=org.hsqldb.jdbcDriver

dburl=jdbc:hsqldb:mem:testdb

#dburl=jdbc:hsqldb:hsql://localhost/sampledb

username=sa

password=

/**************************************************************************************/

. cf.) 위에서 기본으로 memory DB 형식으로 자동 구동하도록 되어 있으나 dburl=jdbc:hsqldb:hsql://localhost/sampledb 과 같이 변경시에는

/lab204-dataaccess/db 상에서 (외부 탐색기에서) runHsqlDB.cmd 를 실행하여 DB Server 를 구동하고 테스트할 수도 있다.



3) transaction 설정

. /lab204-dataaccess/src/test/resources/META-INF/spring/context-transaction.xml 를 작성한다.

/**************************************************************************************/

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dataSource"/>

</bean>

/**************************************************************************************/

. cf.) 여기서는 transaction manager 만을 설정하였고, TestCase 내에서 전역 @Transactional 설정으로 트랜잭션을 일괄 지정하고 있으나 보통 AOP 형식(tx:aop)의 트랜잭션 대상 지정으로 비즈니스 서비스의 메서드에 일괄 지정하는 경우가 많다. cf2.) @Transactional Annotation 으로 대상 메서드에 개별로 따로 지정할 수도 있다.


4) Spring 의 iBATIS 연동 설정

. /lab204-dataaccess/src/test/resources/META-INF/spring/context-sqlMap.xml 를 작성한다.

/**************************************************************************************/

<!-- SqlMap setup for iBATIS Database Layer -->

<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

<property name="configLocation"

value="classpath:/META-INF/sqlmap/sql-map-config.xml" />

<!--

<property name="mappingLocations"

value="classpath:/META-INF/sqlmap/mappings/lab-*.xml" />

-->

<property name="dataSource" ref="dataSource" />

</bean>

/**************************************************************************************/

. 최신 프레임워크 환경에서는 sql-map-config.xml 내에 개별 sql 맵핑 파일일 일일이 지정하는 것이 아니라 위의 mappingLocations 영역을 주석 해제하여 Spring 의 ResourceLoader 형식으로 패턴 매칭에 의거한 일괄 로딩으로 처리가 가능하다. (단, 테스트 결과 CacheModel 등의 일부 기능에서 문제가 발생하는 경우가 있으므로 사용에 유의할것!!)


5) iBATIS 의 sql-map-config 설정 파일 작성

. /lab204-dataaccess/src/test/resources/META-INF/sqlmap/sql-map-config.xml 를 작성한다.

/**************************************************************************************/

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"

"http://www.ibatis.com/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

<settings useStatementNamespaces="false"

cacheModelsEnabled="true"

/>

<!-- Spring 2.5.5 이상, iBATIS 2.3.2 이상에서는 iBATIS 연동을 위한 SqlMapClientFactoryBean 정의 시 mappingLocations 속성으로

Sql 매핑 파일의 일괄 지정이 가능하다.

("sqlMapClient" bean 설정 시 mappingLocations="classpath:/META-INF/sqlmap/mappings/lab-*.xml" 로 지정하였음)

단, sql-map-config-2.dtd 에서 sqlMap 요소를 하나 이상 지정하도록 되어 있으므로 아래의 dummy 매핑 파일을 설정하였다.

-->

<sqlMap resource="META-INF/sqlmap/mappings/lab-dummy.xml" />

<sqlMap resource="META-INF/sqlmap/mappings/lab-dept.xml" />

<sqlMap resource="META-INF/sqlmap/mappings/lab-emp.xml" />

<sqlMap resource="META-INF/sqlmap/mappings/lab-emp-cachemodel.xml" />

<sqlMap resource="META-INF/sqlmap/mappings/lab-emp-dept-resultmap.xml" />

</sqlMapConfig>

/**************************************************************************************/


6) Id Generation Service 설정

. /lab204-dataaccess/src/test/resources/META-INF/spring/context-idgen.xml 를 작성한다.

/**************************************************************************************/

<bean name="primaryTypeSequenceIds"

class="egovframework.rte.fdl.idgnr.impl.EgovSequenceIdGnrService"

destroy-method="destroy">

<property name="dataSource" ref="dataSource" />

<property name="query" value="SELECT NEXT VALUE FOR empseq FROM DUAL" />

</bean>

/**************************************************************************************/

. 여기서는 Hsqldb 를 사용하여 Oracle 의 DUAL 테이블 역할을 할 수 있도록 초기화 스크립트 sql 에 create 하였으며, DB Sequence 기반의 Id Generation 을 사용한 예이다. (위에서 select next value for seq_id from xx 는 Hsqldb 의 특화된 sequence 사용 문법임에 유의!)


7) common 설정

. /lab204-dataaccess/src/test/resources/META-INF/spring/context-common.xml 를 확인한다.

/**************************************************************************************/

<!-- PropertyPlaceholderConfigurer 설정 -->

..

<!-- MessageSource 설정 -->

..

<!-- 전자정부 TraceHandler 설정 관련 -->

..

<!-- 스테레오 타입 Annotation 을 인식하여 Spring bean 으로 자동 등록하기 위한 component-scan 설정 -->

..

/**************************************************************************************/

. 외부 properties 파일을 Container 구동 시 미리 Spring Bean 설정 파일의 속성값으로 대체하여 처리해주는 PropertyPlaceholderConfigurer 설정

. Locale 에 따른 다국어 처리를 쉽게 해주는 messageSource 설정. 여기서는 전자정부 실행환경의 id generation 서비스와 properties 서비스의 메시지 파일과 업무 어플리케이션을 위한 사용자 메시지(/message/message-common - message-common_en_US.properties, message-common_ko_KR.properties 를 확인할 것) 를 지정하였다.

. exception 처리 Handler 와 유사하게 특정한 상황에서 사용자가 Trace Handler 를 지정하여 사용할 수 있도록 전자정부 프레임워크에서 가이드하고 있는 TraceHandler 설정

. component-scan 설정


8) aspect 설정

. /lab204-dataaccess/src/test/resources/META-INF/spring/context-aspect.xml 를 작성한다.

/**************************************************************************************/

<aop:config>

<aop:pointcut id="serviceMethod"

expression="execution(* egovframework.lab..impl.*Impl.*(..))" />


<aop:aspect ref="exceptionTransfer">

<aop:after-throwing throwing="exception"

pointcut-ref="serviceMethod" method="transfer" />

</aop:aspect>

</aop:config>


<bean id="exceptionTransfer" class="egovframework.rte.fdl.cmmn.aspect.ExceptionTransfer">

<property name="exceptionHandlerService">

<list>

<ref bean="defaultExceptionHandleManager" />

</list>

</property>

</bean>


<bean id="defaultExceptionHandleManager"

class="egovframework.rte.fdl.cmmn.exception.manager.DefaultExceptionHandleManager">

<property name="reqExpMatcher" ref="antPathMater" />

<property name="patterns">

<list>

<value>**service.impl.*</value>

</list>

</property>

<property name="handlers">

<list>

<ref bean="egovHandler" />

</list>

</property>

</bean>



<bean id="egovHandler"

class="egovframework.lab.dataaccess.common.JdbcLoggingExcepHndlr" />

/**************************************************************************************/

. Spring AOP(xml 설정 방식) 를 사용하여 비지니스 메서드에서 exception 이 발생한 경우 일괄적으로 ExceptionTransfer 의 transfer 메서드 기능(Advice) 를 수행해 주게 됨. --> Exception logging 및 BizException 형태로 wrapping 하여 재처리하는 Exception 공통처리 후 ExceptionHandleManager 에 의해 관리(설정) 되는 Handler (ex. exception 내용을 메일링 한더던지.. 사용자 구현 가능) 가 자동적으로 추가 수행될 수 있음.




2. EmpService 서비스 작성


1) Interface 작성

. /lab204-dataaccess/src/main/java/egovframework/lab/dataaccess/service/EmpService.java 를 작성한다.

/**************************************************************************************/

public interface EmpService {

public BigDecimal insertEmp(EmpVO empVO) throws Exception;

public void updateEmp(EmpVO empVO) throws Exception;

public void deleteEmp(EmpVO empVO) throws Exception;

public EmpVO selectEmp(EmpVO empVO) throws Exception;

public EmpWithDeptVO selectEmpWithDept(EmpVO empVO) throws Exception;

public EmpIncludesDeptVO selectEmpIncludesDept(EmpVO empVO) throws Exception;

public List<EmpVO> selectEmpList(EmpVO searchVO) throws Exception;

}

/**************************************************************************************/


2) VO 작성

. /lab204-dataaccess/src/main/java/egovframework/lab/dataaccess/service/EmpVO.java 를 작성한다.

/**************************************************************************************/

public class EmpVO extends SearchVO {

private static final long serialVersionUID = -8049578957221741495L;

private BigDecimal empNo;

private String empName;

private String job;

private BigDecimal mgr;

private Date hireDate;

private BigDecimal sal;

private BigDecimal comm;

private BigDecimal deptNo;

public BigDecimal getEmpNo() {

return empNo;

}

public void setEmpNo(BigDecimal empNo) {

this.empNo = empNo;

}

public String getEmpName() {

return empName;

}

public void setEmpName(String empName) {

this.empName = empName;

}

public String getJob() {

return job;

}

public void setJob(String job) {

this.job = job;

}

public BigDecimal getMgr() {

return mgr;

}

public void setMgr(BigDecimal mgr) {

this.mgr = mgr;

}

public Date getHireDate() {

return hireDate;

}

public void setHireDate(Date hireDate) {

this.hireDate = hireDate;

}

public BigDecimal getSal() {

return sal;

}

public void setSal(BigDecimal sal) {

this.sal = sal;

}

public BigDecimal getComm() {

return comm;

}

public void setComm(BigDecimal comm) {

this.comm = comm;

}

public BigDecimal getDeptNo() {

return deptNo;

}

public void setDeptNo(BigDecimal deptNo) {

this.deptNo = deptNo;

}

}

/**************************************************************************************/


. /lab204-dataaccess/src/main/java/egovframework/lab/dataaccess/service/EmpWithDeptVO.java 를 작성한다.

/**************************************************************************************/

public class EmpWithDeptVO extends EmpVO {

/** serialVersionUID */

private static final long serialVersionUID = 2916598732662272200L;

private BigDecimal deptNo;

private String deptName;

private String loc;

public BigDecimal getDeptNo() {

return deptNo;

}

public void setDeptNo(BigDecimal deptNo) {

this.deptNo = deptNo;

}

public String getDeptName() {

return deptName;

}

public void setDeptName(String deptName) {

this.deptName = deptName;

}

public String getLoc() {

return loc;

}

public void setLoc(String loc) {

this.loc = loc;

}

}

/**************************************************************************************/


. /lab204-dataaccess/src/main/java/egovframework/lab/dataaccess/service/EmpIncludesDeptVO.java 를 작성한다.

/**************************************************************************************/

public class EmpIncludesDeptVO extends EmpVO {

/** serialVersionUID */

private static final long serialVersionUID = 2178085836444199596L;

private DeptVO deptVO;

public DeptVO getDeptVO() {

return deptVO;

}

public void setDeptVO(DeptVO deptVO) {

this.deptVO = deptVO;

}

}

/**************************************************************************************/


3) Annotation 을 적용한 Impl

. /lab204-dataaccess/src/main/java/egovframework/lab/dataaccess/service/impl/EmpServiceImpl.java 를 작성한다.

/**************************************************************************************/

@Service("empService")

public class EmpServiceImpl extends AbstractServiceImpl implements EmpService {

@Resource(name = "primaryTypeSequenceIds")

EgovIdGnrService egovIdGnrService;

@Resource(name = "empDAO")

private EmpDAO empDAO;

public BigDecimal insertEmp(EmpVO empVO) throws Exception {

// ID generation Service 를 사용하여 key 를 땀. 여기서

// primaryTypeSequenceIds 는 Sequence 기반임.

BigDecimal generatedEmpNo = egovIdGnrService.getNextBigDecimalId();

log.debug("EmpServiceImpl.insertEmp - generated empNo : " + generatedEmpNo);

empVO.setEmpNo(generatedEmpNo);

empDAO.insertEmp(empVO);

return generatedEmpNo;

}

public void updateEmp(EmpVO empVO) throws Exception {

empDAO.updateEmp(empVO);

}

public void deleteEmp(EmpVO empVO) throws Exception {

empDAO.deleteEmp(empVO);

}

public EmpVO selectEmp(EmpVO empVO) throws Exception {

EmpVO resultVO;

resultVO = empDAO.selectEmp(empVO);

if (resultVO == null) {

throw processException("info.nodata.msg");

}

return resultVO;

}

public List<EmpVO> selectEmpList(EmpVO searchVO) throws Exception {

return empDAO.selectEmpList(searchVO);

}

public EmpWithDeptVO selectEmpWithDept(EmpVO empVO) throws Exception {

EmpWithDeptVO resultVO;

resultVO = empDAO.selectEmpWithDept(empVO);

if (resultVO == null) {

throw processException("info.nodata.msg");

}

return resultVO;

}

public EmpIncludesDeptVO selectEmpIncludesDept(EmpVO empVO) throws Exception {

EmpIncludesDeptVO resultVO;

resultVO = empDAO.selectEmpIncludesDept(empVO);

if (resultVO == null) {

throw processException("info.nodata.msg");

}

return resultVO;

}

}

/**************************************************************************************/


4) DAO 작성

. /lab204-dataaccess/src/main/java/egovframework/lab/dataaccess/service/impl/EmpDAO.java 를 작성한다.

/**************************************************************************************/

@Repository("empDAO")

public class EmpDAO extends EgovAbstractDAO {

public void insertEmp(EmpVO vo) {

insert("insertEmp", vo);

}

public int updateEmp(EmpVO vo) {

return update("updateEmp", vo);

}

public int deleteEmp(EmpVO vo) {

return delete("deleteEmp", vo);

}

public EmpVO selectEmp(EmpVO vo) {

return (EmpVO) selectByPk("selectEmp", vo);

//return (EmpVO) selectByPk("selectEmpUsingCacheModelLRU", vo);

}

@SuppressWarnings("unchecked")

public List<EmpVO> selectEmpList(EmpVO searchVO) {

return list("selectEmpList", searchVO);

}

public EmpWithDeptVO selectEmpWithDept(EmpVO vo) {

return (EmpWithDeptVO) selectByPk("selectEmpWithDept", vo);

}

public EmpIncludesDeptVO selectEmpIncludesDept(EmpVO vo) {

return (EmpIncludesDeptVO) selectByPk("selectEmpIncludesDept", vo);

}

}

/**************************************************************************************/


5) mapping xml 작성

. /lab204-dataaccess/src/test/resources/META-INF/sqlmap/mappings/lab-dummy.xml 를 확인한다.


. /lab204-dataaccess/src/test/resources/META-INF/sqlmap/mappings/lab-emp.xml 를 작성한다.

/**************************************************************************************/

<sqlMap namespace="Emp">

<typeAlias alias="empVO" type="egovframework.lab.dataaccess.service.EmpVO" />

<resultMap id="empResult" class="empVO">

<result property="empNo" column="EMP_NO" />

<result property="empName" column="EMP_NAME" />

<result property="job" column="JOB" />

<result property="mgr" column="MGR" />

<result property="hireDate" column="HIRE_DATE" />

<result property="sal" column="SAL" />

<result property="comm" column="COMM" />

<result property="deptNo" column="DEPT_NO" />

</resultMap>

<insert id="insertEmp" parameterClass="empVO">

<![CDATA[

insert into EMP

(EMP_NO,

EMP_NAME,

JOB,

MGR,

HIRE_DATE,

SAL,

COMM,

DEPT_NO)

values (#empNo#,

#empName#,

#job#,

#mgr#,

#hireDate#,

#sal#,

#comm#,

#deptNo#)

]]>

</insert>

<update id="updateEmp" parameterClass="empVO">

<![CDATA[

update EMP

set EMP_NAME = #empName#,

JOB = #job#,

MGR = #mgr#,

HIRE_DATE = #hireDate#,

SAL = #sal#,

COMM = #comm#,

DEPT_NO = #deptNo#

where EMP_NO = #empNo#

]]>

</update>

<delete id="deleteEmp" parameterClass="empVO">

<![CDATA[

delete from EMP

where EMP_NO = #empNo#

]]>

</delete>

<select id="selectEmp" parameterClass="empVO" resultMap="empResult">

<![CDATA[

select EMP_NO,

EMP_NAME,

JOB,

MGR,

HIRE_DATE,

SAL,

COMM,

DEPT_NO

from EMP

where EMP_NO = #empNo#

]]>

</select>

<select id="selectEmpList" parameterClass="empVO" resultMap="empResult">

<![CDATA[

select EMP_NO,

EMP_NAME,

JOB,

MGR,

HIRE_DATE,

SAL,

COMM,

DEPT_NO

from EMP

where 1 = 1

]]>

<isNotNull prepend="and" property="empNo">

EMP_NO = #empNo#

</isNotNull>

<isNotNull prepend="and" property="empName">

EMP_NAME LIKE '%' || #empName# || '%'

</isNotNull>

</select>

</sqlMap>

/**************************************************************************************/


. /lab204-dataaccess/src/test/resources/META-INF/sqlmap/mappings/lab-emp-cachemodel.xml 를 작성한다.

/**************************************************************************************/

<sqlMap namespace="EmpCache">

<typeAlias alias="empVO" type="egovframework.lab.dataaccess.service.EmpVO" />

<!-- Spring 2.5.5 이상에서 mappingLocations 을 통해 sql mapping 파일 로딩하는 경우 CacheModel 사용에 문제가 있는듯. 주의할것! -->

<cacheModel id="cacheEmpLRU" type="LRU" readOnly="true"

serialize="false">

<flushInterval hours="24" />

<flushOnExecute statement="insertEmp" />

<flushOnExecute statement="updateEmp" />

<flushOnExecute statement="deleteEmp" />

<property name="cache-size" value="1000" />

</cacheModel>

<!-- sql reuse test -->

<sql id="selectEmpReuse">

<![CDATA[

select EMP_NO,

EMP_NAME,

JOB,

MGR,

HIRE_DATE,

SAL,

COMM,

DEPT_NO

from EMP

where 1=1

]]>

<include refid="empWhereEmpNo" />

</sql>

<sql id="empWhereEmpNo">

<isNotNull prepend="and" property="empNo">

EMP_NO = #empNo#

</isNotNull>

</sql>

<!-- CacheModel test -->

<select id="selectEmpUsingCacheModelLRU" parameterClass="empVO"

resultMap="Emp.empResult" cacheModel="cacheEmpLRU">

<include refid="selectEmpReuse" />

</select>

</sqlMap>

/**************************************************************************************/


. /lab204-dataaccess/src/test/resources/META-INF/sqlmap/mappings/lab-emp-dept-resultmap.xml 를 작성한다.

/**************************************************************************************/

<sqlMap namespace="EmpResultMap">

<typeAlias alias="empWithDeptVO" type="egovframework.lab.dataaccess.service.EmpWithDeptVO" />

<typeAlias alias="empIncludesDeptVO" type="egovframework.lab.dataaccess.service.EmpIncludesDeptVO" />

<typeAlias alias="deptIncludesEmpListVO" type="egovframework.lab.dataaccess.service.DeptIncludesEmpListVO" />

<resultMap id="empWithDeptResult" class="empWithDeptVO" extends="Emp.empResult">

<!--<result property="deptNo" column="DEPT_NO"/>-->

<result property="deptName" column="DEPT_NAME"/>

<result property="loc" column="LOC"/>

</resultMap>

<resultMap id="empIncludesDeptResult" class="empIncludesDeptVO" extends="Emp.empResult">

<!--

Emp-Dept 1:1 relation

테스트 결과 resultMap 의 참조 시 sql-map-config.xml 의

useStatementNamespaces="false" 와 상관없이 namespace prefix 를 써야 하는듯

-->

<result property="deptVO" resultMap="Dept.deptResult" />

</resultMap>

<!-- 1:N 인 경우 groupBy 속성을 명시 -->

<resultMap id="deptIncludesEmpListResult" class="deptIncludesEmpListVO" extends="Dept.deptResult" groupBy="deptNo">

<!-- Dept-EmpList 1:N relation -->

<result property="empVOList" resultMap="Emp.empResult" />

</resultMap>

<select id="selectEmpWithDept" parameterClass="empVO" resultMap="empWithDeptResult">

<![CDATA[

select EMP_NO,

EMP_NAME,

JOB,

MGR,

HIRE_DATE,

SAL,

COMM,

A.DEPT_NO,

B.DEPT_NAME,

B.LOC

from EMP A, DEPT B

where A.DEPT_NO = B.DEPT_NO

and A.EMP_NO = #empNo#

]]>

</select>

<select id="selectEmpIncludesDept" parameterClass="empVO" resultMap="empIncludesDeptResult">

<![CDATA[

select EMP_NO,

EMP_NAME,

JOB,

MGR,

HIRE_DATE,

SAL,

COMM,

A.DEPT_NO,

B.DEPT_NAME,

B.LOC

from EMP A, DEPT B

where A.DEPT_NO = B.DEPT_NO

and A.EMP_NO = #empNo#

]]>

</select>

<select id="selectDeptIncludesEmpList" parameterClass="deptVO" resultMap="deptIncludesEmpListResult">

<![CDATA[

select A.DEPT_NO as DEPT_NO,

DEPT_NAME,

LOC,

EMP_NO,

EMP_NAME,

JOB,

MGR,

HIRE_DATE,

SAL,

COMM

from DEPT A,

EMP B

where A.DEPT_NO = B.DEPT_NO

and A.DEPT_NO = #deptNo#

order by B.EMP_NO

]]>

</select>

</sqlMap>

/**************************************************************************************/


6) Testcase 작성

. /lab204-dataaccess/src/test/java/egovframework/lab/dataaccess/service/EmpServiceTest.java 를 작성한다.

/**************************************************************************************/

package egovframework.lab.dataaccess.service;

import static org.junit.Assert.assertEquals;

import static org.junit.Assert.assertNotNull;

import static org.junit.Assert.assertTrue;

import static org.junit.Assert.fail;

import java.math.BigDecimal;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.List;

import javax.annotation.Resource;

import javax.sql.DataSource;

import org.junit.Before;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.core.io.ClassPathResource;

import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import org.springframework.test.context.transaction.TransactionConfiguration;

import org.springframework.test.jdbc.SimpleJdbcTestUtils;

import org.springframework.transaction.annotation.Transactional;

import egovframework.rte.fdl.cmmn.exception.EgovBizException;

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = {"classpath*:META-INF/spring/context-*" })

@TransactionConfiguration(transactionManager = "txManager", defaultRollback = false)

@Transactional

public class EmpServiceTest {

@Resource(name = "dataSource")

DataSource dataSource;

@Resource(name = "empService")

EmpService empService;

@Before

public void onSetUp() throws Exception {

// 테스트 편의상 매 테스트메서드 수행전 외부의 sql file 로부터 DB 초기화

// (기존 테이블 삭제/생성)

SimpleJdbcTestUtils.executeSqlScript(

new SimpleJdbcTemplate(dataSource), new ClassPathResource(

"META-INF/testdata/sample_schema_hsql.sql"), true);

}

public EmpVO makeVO() throws ParseException {

EmpVO vo = new EmpVO();

// empNo 는 Biz. 서비스 내에서 id generation service 에

// 의해 key 를 따고 설정할 것임.

vo.setEmpName("홍길동");

vo.setJob("개발자");

vo.setMgr(new BigDecimal(7902));

SimpleDateFormat sdf =

new SimpleDateFormat("yyyy-MM-dd", java.util.Locale.getDefault());

vo.setHireDate(sdf.parse("2009-07-09"));

vo.setSal(new BigDecimal(1000));

vo.setComm(new BigDecimal(0));

vo.setDeptNo(new BigDecimal(20));

return vo;

}

public void checkResult(EmpVO vo, EmpVO resultVO) {

assertNotNull(resultVO);

assertEquals(vo.getEmpNo(), resultVO.getEmpNo());

assertEquals(vo.getEmpName(), resultVO.getEmpName());

assertEquals(vo.getJob(), resultVO.getJob());

assertEquals(vo.getMgr(), resultVO.getMgr());

assertEquals(vo.getHireDate(), resultVO.getHireDate());

assertEquals(vo.getSal(), resultVO.getSal());

assertEquals(vo.getComm(), resultVO.getComm());

assertEquals(vo.getDeptNo(), resultVO.getDeptNo());

}

@Test

public void testInsertEmp() throws Exception {

EmpVO vo = makeVO();

// insert

BigDecimal empNo = empService.insertEmp(vo);

vo.setEmpNo(empNo);

// select

EmpVO resultVO = empService.selectEmp(vo);

// check

checkResult(vo, resultVO);

}

@Test

public void testUpdateEmp() throws Exception {

EmpVO vo = makeVO();

// insert

BigDecimal empNo = empService.insertEmp(vo);

vo.setEmpNo(empNo);

// data change

vo.setEmpName("홍길순");

vo.setJob("설계자");

// update

empService.updateEmp(vo);

// select

EmpVO resultVO = empService.selectEmp(vo);

// check

checkResult(vo, resultVO);

}

@Test

public void testDeleteEmp() throws Exception {

EmpVO vo = makeVO();

// insert

BigDecimal empNo = empService.insertEmp(vo);

vo.setEmpNo(empNo);

// delete

empService.deleteEmp(vo);

// select

try {

@SuppressWarnings("unused")

EmpVO resultVO = empService.selectEmp(vo);

fail("EgovBizException 이 발생해야 합니다.");

} catch (Exception e) {

assertNotNull(e);

// 여기서는 비지니스 단에서 명시적으로 exception 처리 하였음.

// AbstractServiceImpl 을 extends 하고

// processException("info.nodata.msg"); 과

// 같이 메서드 콜 형태로 처리

assertTrue(e instanceof EgovBizException);

assertEquals("info.nodata.msg", ((EgovBizException) e)

.getMessageKey());

assertEquals("해당 데이터가 없습니다.", e.getMessage());

}

}

@Test

public void testSelectEmpList() throws Exception {

EmpVO vo = makeVO();

// insert

BigDecimal empNo = empService.insertEmp(vo);

vo.setEmpNo(empNo);

// 검색조건으로 key 설정

EmpVO searchVO = new EmpVO();

searchVO.setEmpNo(vo.getEmpNo());

// selectList

List<EmpVO> resultList = empService.selectEmpList(searchVO);

// key 조건에 대한 결과는 한건일 것임

assertNotNull(resultList);

assertTrue(resultList.size() > 0);

assertEquals(1, resultList.size());

checkResult(vo, resultList.get(0));

// 검색조건으로 name 설정 - '%' || #empName# || '%'

EmpVO searchVO2 = new EmpVO();

searchVO2.setEmpName(""); // '%' || '' || '%'

// --> '%%'

// selectList

List<EmpVO> resultList2 = empService.selectEmpList(searchVO2);

// like 조건에 대한 결과는 한건 이상일 것임

assertNotNull(resultList2);

assertTrue(resultList2.size() > 0);

}

@Test

public void testSelectEmpWithDept() throws Exception {

EmpVO vo = makeVO();

// insert

BigDecimal empNo = empService.insertEmp(vo);

vo.setEmpNo(empNo);

// select EmpWithDept

EmpWithDeptVO resultVO = empService.selectEmpWithDept(vo);

// check - emp data

checkResult(vo, resultVO);

// check - emp's dept data - 위 makeVO() 에서 7902 - RESEARCH 로 설정했음.

assertEquals(vo.getDeptNo(), resultVO.getDeptNo());

assertEquals("RESEARCH", resultVO.getDeptName());

assertEquals("DALLAS", resultVO.getLoc());

}

@Test

public void testSelectEmpIncludesDept() throws Exception {

EmpVO vo = makeVO();

// insert

BigDecimal empNo = empService.insertEmp(vo);

vo.setEmpNo(empNo);

// select EmpIncludesDept

EmpIncludesDeptVO resultVO = empService.selectEmpIncludesDept(vo);

// check - emp data

checkResult(vo, resultVO);

// check - emp's dept data - 위 makeVO() 에서 7902 - RESEARCH 로 설정했음.

assertEquals(vo.getDeptNo(), resultVO.getDeptVO().getDeptNo());

assertEquals("RESEARCH", resultVO.getDeptVO().getDeptName());

assertEquals("DALLAS", resultVO.getDeptVO().getLoc());

}

}

/**************************************************************************************/



3. DeptService 서비스 작성


1) Interface 작성

. /lab204-dataaccess/src/main/java/egovframework/lab/dataaccess/service/DeptService.java 를 작성한다.

/**************************************************************************************/

public interface DeptService {

public void insertDept(DeptVO deptVO) throws Exception;

public void updateDept(DeptVO deptVO) throws Exception;

public void deleteDept(DeptVO deptVO) throws Exception;

public DeptVO selectDept(DeptVO deptVO) throws Exception;

public DeptIncludesEmpListVO selectDeptIncludesEmpList(DeptVO deptVO) throws Exception;

public List<DeptVO> selectDeptList(DeptVO searchVO) throws Exception;

}

/**************************************************************************************/


2) VO 작성

. /lab204-dataaccess/src/main/java/egovframework/lab/dataaccess/service/DeptVO.java 를 작성한다.

/**************************************************************************************/

public class DeptVO extends SearchVO {

private static final long serialVersionUID = -5658611204548724246L;

private BigDecimal deptNo;

private String deptName;

private String loc;

public BigDecimal getDeptNo() {

return deptNo;

}

public void setDeptNo(BigDecimal deptNo) {

this.deptNo = deptNo;

}

public String getDeptName() {

return deptName;

}

public void setDeptName(String deptName) {

this.deptName = deptName;

}

public String getLoc() {

return loc;

}

public void setLoc(String loc) {

this.loc = loc;

}

}

/**************************************************************************************/


. /lab204-dataaccess/src/main/java/egovframework/lab/dataaccess/service/DeptIncludesEmpListVO.java 를 작성한다.

/**************************************************************************************/

public class DeptIncludesEmpListVO extends DeptVO {

/** serialVersionUID */

private static final long serialVersionUID = -6098129034400325088L;

private List<EmpVO> empVOList;

public List<EmpVO> getEmpVOList() {

return empVOList;

}

public void setEmpVOList(List<EmpVO> empVOList) {

this.empVOList = empVOList;

}

}

/**************************************************************************************/


3) Annotation 을 적용한 Impl

. /lab204-dataaccess/src/main/java/egovframework/lab/dataaccess/service/impl/DeptServiceImpl.java 를 작성한다.

/**************************************************************************************/

@Service("deptService")

public class DeptServiceImpl extends AbstractServiceImpl implements DeptService {

@Resource(name = "deptDAO")

private DeptDAO deptDAO;

public void insertDept(DeptVO deptVO) throws Exception {

deptDAO.insertDept(deptVO);

}

public void updateDept(DeptVO deptVO) throws Exception {

deptDAO.updateDept(deptVO);

}

public void deleteDept(DeptVO deptVO) throws Exception {

deptDAO.deleteDept(deptVO);

}

public DeptVO selectDept(DeptVO deptVO) throws Exception {

DeptVO resultVO = deptDAO.selectDept(deptVO);

if (resultVO == null) {

throw processException("info.nodata.msg");

}

return resultVO;

}

public List<DeptVO> selectDeptList(DeptVO searchVO) throws Exception {

return deptDAO.selectDeptList(searchVO);

}

public DeptIncludesEmpListVO selectDeptIncludesEmpList(DeptVO deptVO)

throws Exception {

DeptIncludesEmpListVO resultVO = deptDAO.selectDeptIncludesEmpList(deptVO);

if (resultVO == null) {

throw processException("info.nodata.msg");

}

return resultVO;

}

}

/**************************************************************************************/


4) DAO 작성

. /lab204-dataaccess/src/main/java/egovframework/lab/dataaccess/service/impl/DeptDAO.java 를 작성한다.

/**************************************************************************************/

@Repository("deptDAO")

public class DeptDAO extends EgovAbstractDAO {

public void insertDept(DeptVO vo) {

insert("insertDept", vo);

}

public int updateDept(DeptVO vo) {

return update("updateDept", vo);

}

public int deleteDept(DeptVO vo) {

return delete("deleteDept", vo);

}

public DeptVO selectDept(DeptVO vo) {

return (DeptVO)selectByPk("selectDept", vo);

}

@SuppressWarnings("unchecked")

public List<DeptVO> selectDeptList(DeptVO searchVO) {

return list("selectDeptList", searchVO);

}

public DeptIncludesEmpListVO selectDeptIncludesEmpList(DeptVO vo) {

return (DeptIncludesEmpListVO)selectByPk("selectDeptIncludesEmpList", vo);

}

}

/**************************************************************************************/


5) mapping xml 작성


. /lab204-dataaccess/src/test/resources/META-INF/sqlmap/mappings/lab-dept.xml 를 작성한다.

/**************************************************************************************/

<sqlMap namespace="Dept">

<typeAlias alias="deptVO" type="egovframework.lab.dataaccess.service.DeptVO" />

<resultMap id="deptResult" class="deptVO">

<result property="deptNo" column="DEPT_NO" />

<result property="deptName" column="DEPT_NAME" />

<result property="loc" column="LOC" />

</resultMap>

<insert id="insertDept" parameterClass="deptVO">

insert into DEPT

(DEPT_NO,

DEPT_NAME,

LOC)

values (#deptNo#,

#deptName#,

#loc#)

</insert>

<select id="selectDept" parameterClass="deptVO" resultMap="deptResult">

<![CDATA[

select DEPT_NO,

DEPT_NAME,

LOC

from DEPT

where DEPT_NO = #deptNo#

]]>

</select>

<update id="updateDept" parameterClass="deptVO">

update DEPT

set DEPT_NAME = #deptName#,

LOC = #loc#

where DEPT_NO = #deptNo#

</update>

<delete id="deleteDept" parameterClass="deptVO">

delete from DEPT

where DEPT_NO = #deptNo#

</delete>

<select id="selectDeptList" parameterClass="deptVO" resultMap="deptResult">

<![CDATA[

select DEPT_NO,

DEPT_NAME,

LOC

from DEPT

where 1 = 1

]]>

<isNotNull prepend="and" property="deptNo">

DEPT_NO = #deptNo#

</isNotNull>

<isNotNull prepend="and" property="deptName">

DEPT_NAME LIKE '%' || #deptName# || '%'

</isNotNull>

</select>

</sqlMap>

/**************************************************************************************/


. /lab204-dataaccess/src/test/resources/META-INF/sqlmap/mappings/lab-emp-dept-resultmap.xml 에서 selectDeptIncludesEmpList 쿼리 관련 resultMap 과 sql 설정 확인

/**************************************************************************************/

<sqlMap namespace="EmpResultMap">

..

<typeAlias alias="deptIncludesEmpListVO" type="egovframework.lab.dataaccess.service.DeptIncludesEmpListVO" />

..

<!-- 1:N 인 경우 groupBy 속성을 명시 -->

<resultMap id="deptIncludesEmpListResult" class="deptIncludesEmpListVO" extends="Dept.deptResult" groupBy="deptNo">

<!-- Dept-EmpList 1:N relation -->

<result property="empVOList" resultMap="Emp.empResult" />

</resultMap>

..


<select id="selectDeptIncludesEmpList" parameterClass="deptVO" resultMap="deptIncludesEmpListResult">

<![CDATA[

select A.DEPT_NO as DEPT_NO,

DEPT_NAME,

LOC,

EMP_NO,

EMP_NAME,

JOB,

MGR,

HIRE_DATE,

SAL,

COMM

from DEPT A,

EMP B

where A.DEPT_NO = B.DEPT_NO

and A.DEPT_NO = #deptNo#

order by B.EMP_NO

]]>

</select>

</sqlMap>

/**************************************************************************************/


6) Testcase 작성

. /lab204-dataaccess/src/test/java/egovframework/lab/dataaccess/service/DeptServiceTest.java 를 작성한다.

/**************************************************************************************/

package egovframework.lab.dataaccess.service;

import static org.junit.Assert.assertEquals;

import static org.junit.Assert.assertNotNull;

import static org.junit.Assert.assertTrue;

import static org.junit.Assert.fail;

import java.math.BigDecimal;

import java.util.List;

import javax.annotation.Resource;

import javax.sql.DataSource;

import org.junit.Before;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.core.io.ClassPathResource;

import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import org.springframework.test.context.transaction.TransactionConfiguration;

import org.springframework.test.jdbc.SimpleJdbcTestUtils;

import org.springframework.transaction.annotation.Transactional;

import egovframework.rte.fdl.cmmn.exception.EgovBizException;

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = {"classpath*:META-INF/spring/context-*" })

@TransactionConfiguration(transactionManager = "txManager", defaultRollback = false)

@Transactional

public class DeptServiceTest {

@Resource(name = "dataSource")

DataSource dataSource;

@Resource(name = "deptService")

DeptService deptService;

@Before

public void onSetUp() throws Exception {

// 테스트 편의상 매 테스트메서드 수행전 외부의 sql file 로부터 DB 초기화

// (기존 테이블 삭제/생성)

SimpleJdbcTestUtils.executeSqlScript(

new SimpleJdbcTemplate(dataSource), new ClassPathResource(

"META-INF/testdata/sample_schema_hsql.sql"), true);

}

public DeptVO makeVO() {

return makeVO(90);

}

public DeptVO makeVO(int deptNo) {

DeptVO vo = new DeptVO();

vo.setDeptNo(new BigDecimal(deptNo));

vo.setDeptName("test 부서");

vo.setLoc("test 위치");

return vo;

}

public void checkResult(DeptVO vo, DeptVO resultVO) {

assertNotNull(resultVO);

assertEquals(vo.getDeptNo(), resultVO.getDeptNo());

assertEquals(vo.getDeptName(), resultVO.getDeptName());

assertEquals(vo.getLoc(), resultVO.getLoc());

}

@Test

public void testInsertDept() throws Exception {

DeptVO vo = makeVO();

// insert

deptService.insertDept(vo);

// select

DeptVO resultVO = deptService.selectDept(vo);

// check

checkResult(vo, resultVO);

}

@Test

public void testUpdateDept() throws Exception {

DeptVO vo = makeVO();

// insert

deptService.insertDept(vo);

// data change

vo.setDeptName("upd Dept");

vo.setLoc("upd loc");

// update

deptService.updateDept(vo);

// select

DeptVO resultVO = deptService.selectDept(vo);

// check

checkResult(vo, resultVO);

}

@Test

public void testDeleteDept() throws Exception {

DeptVO vo = makeVO();

// insert

deptService.insertDept(vo);

// delete

deptService.deleteDept(vo);

// select

try {

@SuppressWarnings("unused")

DeptVO resultVO = deptService.selectDept(vo);

fail("EgovBizException 이 발생해야 합니다.");

} catch (Exception e) {

assertNotNull(e);

// 여기서는 비지니스 단에서 명시적으로 exception 처리 하였음.

// AbstractServiceImpl 을 extends 하고

// processException("info.nodata.msg"); 과

// 같이 메서드 콜 형태로 처리

assertTrue(e instanceof EgovBizException);

assertEquals("info.nodata.msg", ((EgovBizException) e)

.getMessageKey());

assertEquals("해당 데이터가 없습니다.", e.getMessage());

}

}

@Test

public void testSelectDeptList() throws Exception {

DeptVO vo = makeVO();

// insert

deptService.insertDept(vo);

// 검색조건으로 key 설정

DeptVO searchVO = new DeptVO();

searchVO.setDeptNo(vo.getDeptNo());

// selectList

List<DeptVO> resultList = deptService.selectDeptList(searchVO);

// key 조건에 대한 결과는 한건일 것임

assertNotNull(resultList);

assertTrue(resultList.size() > 0);

assertEquals(1, resultList.size());

checkResult(vo, resultList.get(0));

// 검색조건으로 name 설정 - '%' || #deptName# || '%'

DeptVO searchVO2 = new DeptVO();

searchVO2.setDeptName(""); // '%' || '' || '%' --> '%%'

// selectList

List<DeptVO> resultList2 = deptService.selectDeptList(searchVO2);

// like 조건에 대한 결과는 한건 이상일 것임

assertNotNull(resultList2);

assertTrue(resultList2.size() > 0);

}

@Test

public void testSelectDeptIncludesEmpList() throws Exception {

DeptVO vo = new DeptVO();

vo.setDeptNo(new BigDecimal(20));

// select EmpIncludesDept

DeptIncludesEmpListVO resultVO = deptService.selectDeptIncludesEmpList(vo);

// check - 초기화 데이터에 따라 deptNo 20 인 data

assertEquals(new BigDecimal(20), resultVO.getDeptNo());

assertEquals("RESEARCH", resultVO.getDeptName());

assertEquals("DALLAS", resultVO.getLoc());

// check - dept's empList data

// 초기화 데이터에 따라

// EMP_NO EMP_NAME JOB MGR HIRE_DATE SAL COMM DEPT_NO

// ------ -------- ------- ---- ---------- ---- ------ -------

// 7369 SMITH CLERK 7902 1980-12-17 800 (null) 20

// 7566 JONES MANAGER 7839 1981-04-02 2975 (null) 20

// 7788 SCOTT ANALYST 7566 1987-04-19 3000 (null) 20

// 7876 ADAMS CLERK 7788 1987-05-23 1100 (null) 20

// 7902 FORD ANALYST 7566 1981-12-03 3000 (null) 20

assertEquals(5, resultVO.getEmpVOList().size());

assertEquals(new BigDecimal(7369), resultVO.getEmpVOList().get(0).getEmpNo());

assertEquals(new BigDecimal(7566), resultVO.getEmpVOList().get(1).getEmpNo());

assertEquals(new BigDecimal(7788), resultVO.getEmpVOList().get(2).getEmpNo());

assertEquals(new BigDecimal(7876), resultVO.getEmpVOList().get(3).getEmpNo());

assertEquals(new BigDecimal(7902), resultVO.getEmpVOList().get(4).getEmpNo());

}

}

/**************************************************************************************/



4. Sql 로깅 설정

1) /lab204-dataaccess/src/test/resources/META-INF/spring/jdbc.properties 를 다음과 같이 변경한다.

/**************************************************************************************/

driver=net.sf.log4jdbc.DriverSpy

dburl=jdbc:log4jdbc:hsqldb:mem:testdb

#dburl=jdbc:log4jdbc:hsqldb:hsql://localhost/sampledb

username=sa

password=

/**************************************************************************************/


2) /lab204-dataaccess/src/test/resources/log4j.xml 에 다음 Logger 를 추가한다.

/**************************************************************************************/

<!-- log SQL with timing information, post execution -->

<logger name="jdbc.sqltiming" additivity="false">

<level value="INFO" />

<appender-ref ref="console" />

</logger>

/**************************************************************************************/


 


 

[출처] http://blog.naver.com/heehow/140152784894

반응형