블로그 이미지

카테고리

분류 전체보기 (11)
Programming (6)
Baskek Ball (0)
Diary (2)
etc (1)
Picture (2)
Total
Today
Yesterday
02-19 14:10

달력

« » 2025.2
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

공지사항

태그목록

최근에 올라온 글

정말 오랜만에 방문한 춘천, 그리고 한림성심대학 체육관.

8월 13일 토요일.
업무와 기타 여러가지 일들 때문에 몸도 지치고, 정신적으로도 피곤하고.....

다짜고짜 덕은형님한테 연락해서
"형 저 춘천갈게요. 술사주세요!!!!!!!!"
그럼에도 불구하고 늦은시간 흔쾌히 나오셔서 돼지갈비&소주, 그리고 맥주를 사주신 형님.
고맙습니다 ㅠㅠ

철없고 어린동생의 투정도 하나하나 다 들어주시고..


8월 14일 일요일.
얼마만인지 기억도 잘 안날만큼 오랜만에 코트를 다시 찾았다.
코트 왁싱도 새로해놔서 잘 관리된 코트에서만 들을 수 있는 특유의 경쾌한 소리.
농구화와 코트의 부딪힘으로 인해 생기는 그 소리를 들으니 기분 좋드라 ㅋㅋ

플레이하는 사진을 찍고 싶었지만.. 저질체력으로 인한 저질플레이 ㅠㅠㅠㅠㅠ
그래도 뭐.. 속공찬스에서 컷인플레이 몇개 정도는 성공... 박스아웃도 아직 녹슬지 않은거 같고..
체력이랑 슛감만 어떻게 좀.....

TS Bounce Commander @IL-Song Gym.


TS Bounce Commander @IL-Song Gym.
Posted by 그리브스
, |

Generic이란 무엇일까요? Java 1.5 버전부터 나온 새로운 문법입니다미결정된 선언을 컴파일 타임으로 미루므로써

프로그래밍의 유연성을 부여할 수 있게 되었습니다말이 좀 이상한데 한번 보면 될듯합니다.

 

일반적으로 insert, select, update, delete는 기본적으로 작성해야 되므로 이를 Abstract로 뽑아내어 공통으로 사용하고

필요한 것들만 만들어 사용하면 프로그램의 생산성이 향상되겠죠근데 이때 문제가 여러 개의 vo는 서로 다른 형태를

취하고 있으므로 이를 공통을 맞춰줄 수가 없게 됩니다이때 Generic을 사용하여 문제를 해결할 수 있습니다. Generic

class파일을 생성하는 compile타임에 실제 선언된 타입으로 컴파일 됩니다.

package org.power.dao;

 

public interface GenericDAO<V, K> {

 

       public void insert(V vo) throws Exception;

       public V select(K key) throws Exception;

       public void update(V vo) throws Exception;

       public void delete(K key) throws Exception;

}

 

공통으로 사용되는 코드를 Generic을 사용하여 Abstract로 구현해 보았습니다.

package org.power.dao;

 

import java.io.IOException;

import java.io.Reader;

 

import com.ibatis.common.resources.Resources;

import com.ibatis.sqlmap.client.SqlMapClient;

import com.ibatis.sqlmap.client.SqlMapClientBuilder;

 

public class AbstractDAO<V, K> implements GenericDAO<V, K>{

      

       protected static SqlMapClient sqlMap;

       protected String namespace;

      

       static {

 

             try {

                    Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");

                    sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);

                    reader.close();

             catch (IOException e) {

                    // Fail fast.

                    throw new RuntimeException("Something bad happened while building the SqlMapClient instance." + e, e);

             }

       }

      

       @Override

       public void insert(V vo) throws Exception {

             sqlMap.insert(namespace + ".insertBBS", vo);

            

       }

 

       @Override

       public V select(K key) throws Exception {

             return (V) sqlMap.queryForObject(namespace + ".selectBBS", key);

       }

 

       @Override

       public void update(V vo) throws Exception {

            

             sqlMap.update(namespace + ".updateBBS", vo);

            

       }

 

       @Override

       public void delete(K key) throws Exception {

             sqlMap.delete(namespace + ".deleteBBS", key);

            

       }

      

}

 

위에 namespace가 있습니다이는 서로 다른 성격의 insert, select, update, delete작업을 하는 xml의 분리하기 위해 사용됩니다.

그러므로 xml도 해당 namespace를 설정해 주어야 합니다.

 

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

<!DOCTYPE sqlMapConfig     

    PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"     

    "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

 

<sqlMapConfig>

 

       <settings useStatementNamespaces="true"/>

      

       <transactionManager type="JDBC" commitRequired="false">

             <dataSource type="SIMPLE">

                    <property name="JDBC.Driver" value="oracle.jdbc.driver.OracleDriver"/>

                    <property name="JDBC.ConnectionURL"value="jdbc:oracle:thin:@127.0.0.1:1521:ORCL" />

                    <property name="JDBC.Username" value="tony" />

                    <property name="JDBC.Password" value="1234" />

             </dataSource>

       </transactionManager>

 

       <sqlMap resource="BBS.xml" />

 

</sqlMapConfig>

 

 

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

 

<!DOCTYPE sqlMap     

    PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"     

    "http://ibatis.apache.org/dtd/sql-map-2.dtd">

 

<sqlMap namespace="BBS">

      

 

       <insert id="insertBBS" parameterClass="org.power.vo.BbsVO">

             <![CDATA[

                    INSERT INTO TBL_BBS (bbsno, title, content, writer, hits)

                    VALUES (SEQ_BBS_NO.NEXTVAL, #title#, #content#, #writer#, #hits#)

             ]]>

       </insert>

      

       <select id="selectBBS" resultClass="org.power.vo.BbsVO">

             <![CDATA[

                    SELECT bbsno, title, content, writer, hits, regdate

                    FROM TBL_BBS

                    WHERE bbsno = #bbsno#

             ]]>

       </select>

      

       <update id="updateBBS" parameterClass="org.power.vo.BbsVO">

             <![CDATA[

                    UPDATE TBL_BBS SET title=#title#, content=#content#,

                    writer=#writer#, hits=#hits#, regdate=#regdate#

                    where bbsno=#bbsno#

             ]]>

       </update>

      

       <delete id="deleteBBS" parameterClass="java.lang.Integer">

             <![CDATA[

                    DELETE FROM TBL_BBS WHERE bbsno=#bbsno#

             ]]>

       </delete>

      

</sqlMap>

 

 

 

BbsDAO를 만들어 보겠습니다즉 게시판 하나가 되겠지요아래에 보면 선언된 인터페이스가 하나도 없죠이는GenericDAO에서

선언되어 있으며 BbsDAO에서는 해당 코드를 물려 받습니다다만 여기서 중요한 것이 파라메터값이 확정된다는 것입니다.

package org.power.dao;

 

import org.power.vo.BbsVO;

 

public interface BbsDAO extends GenericDAO<BbsVO, Integer> {

      

       //만약 insert, select, update, delete 이외의 DAO메소드가 필요하다면 여기에

       //인터페이스를 선언하고 Implements하면 됩니다.

      

}

 

구현 클래스를 보면 아래와 같습니다기본적으로 Abstract의 코드를 물려 받으므로 BbsDAO와 같이 BbsDAOImpl에도 별다른 코드가

없습니다다만 여기서 namespace를 결정해 주어야 합니다.

package org.power.dao;

 

import org.power.vo.BbsVO;

 

public class BbsDAOImpl extends AbstractDAO<BbsVO, Integer> implements BbsDAO {

 

       public BbsDAOImpl() {

             super();

             namespace = "BBS";

       }

      

       //BbsDAO에서 기본 insert, select, update, delete외에 DAO 메소드를 추가하였다면

       //이부분에 구현을 해주시면 됩니다.

      

}

 

자 이제 DAO를 테스트 해보기로 하겠습니다테스트 코드는 기존과 동일합니다.

package org.power.test;

 

import org.power.dao.BbsDAO;

import org.power.dao.BbsDAOImpl;

import org.power.vo.BbsVO;

 

import junit.framework.TestCase;

 

public class BbsDAOTest extends TestCase {

 

       private BbsDAO bbsDao;

 

       protected void setUp() throws Exception {

             super.setUp();

 

             bbsDao = new BbsDAOImpl();

 

       }

 

       public void testInsert() {

 

 

             BbsVO vo = new BbsVO();

 

             try {

 

                    vo.setTitle("Generic 사용한 설계새로운 글을 등록합니다.(타이틀)");

                    vo.setContent("Generic 사용한 설계새로운 글을 내용을합니다.");

                    vo.setHits(100);

                    vo.setWriter("S002");

 

                    bbsDao.insert(vo);

 

             catch (Exception e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

             }

 

       }

 

       public void testSelect() {

 

             BbsVO vo = new BbsVO();

 

             try {

                    vo = bbsDao.select(700);

 

                    System.out.println(vo.getBbsno());

                    System.out.println(vo.getTitle());

                    System.out.println(vo.getContent());

                    System.out.println(vo.getWriter());

                    System.out.println(vo.getRegdate());

 

             catch (Exception e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

             }

 

       }

 

       public void testUpdate() {

 

             BbsVO vo = new BbsVO();

 

             try {

 

                    vo = bbsDao.select(600);

 

                    vo.setTitle("800  타이틀 수정입니다.");

                    vo.setContent("800  내용 수정한 내용입니다");

                    vo.setHits(0);

 

                    bbsDao.update(vo);

 

             catch (Exception e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

             }

 

       }

 

       public void testDelete() {

 

             try {

 

                    bbsDao.delete(1000);

 

             catch (Exception e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

             }

 

       }

 

}

 

 

Insert 정상적으로 작동함.

 

Select 정상적으로 작동합니다.

 

이제 완성하였습니다자 그러면 새로운 테이블이 생성되고 똑 같은 기능의 게시판을 만든다고 했을 때는 새로운 인터페이스만 선언하고 xml파일만 만들어주면 새로운 게시판이 생성될 것입니다.


[출처] http://blog.naver.com/byebird


 

'Programming > Java' 카테고리의 다른 글

Ibatis 라이브러리를 이용한 VO,DAO의 구현  (0) 2011.07.19
JDBC를 이용한 VO,DAO의 구현  (0) 2011.07.19
Posted by 그리브스
, |

전에 JDBC를 이용하여 VO, DAO설계를 해보았습니다. 그러다 보니 많은 부분 불필요한 소스가 생겨나고 생산성이 떨어지는 것을 경험하였을 것입니다. 이를 해결하기 위하여 Ibatis라는 라이브러리를 사용해 보겠습니다.

Ibatis는 JDBC를 대체하는 것이 아니라 JDBC를 효율적으로 사용하는 라이브러리라 할 수 있습니다. 그 핵심에는 DI(Dependency injection)패턴이 있습니다. 각종 프레임워크에서는 이 DI를 적극적으로 활용하고 있으며 특히 Java 1.5부터는 Annotation을 활용하여 DI가 기본을 이루고 있습니다. DI패턴과 Annotation은 나중에 알아 보고요.

우선은 ibatis를 활용하여 vo와 dao를 구현해보겠습니다.

 

테이블과 vo, dao인터페이스는 기존 생성은 기존과 같습니다.

package org.power.vo;

 

import java.util.Date;

 

public class BbsVO {

      

       private int bbsno;

       private String title;

       private String writer;

       private int hits;

       private String content;

       private Date regdate;

      

       public int getBbsno() {

             return bbsno;

       }

       public void setBbsno(int bbsno) {

             this.bbsno = bbsno;

       }

       public String getTitle() {

             return title;

       }

       public void setTitle(String title) {

             this.title = title;

       }

       public String getWriter() {

             return writer;

       }

       public void setWriter(String writer) {

             this.writer = writer;

       }

       public int getHits() {

             return hits;

       }

       public void setHits(int hits) {

             this.hits = hits;

       }

       public String getContent() {

             return content;

       }

       public void setContent(String content) {

             this.content = content;

       }

       public Date getRegdate() {

             return regdate;

       }

       public void setRegdate(Date regdate) {

             this.regdate = regdate;

       }

      

}

 

package org.power.dao;

import org.power.vo.BbsVO;

 

public interface BbsDAO {

      

       public void insert(BbsVO vo) throws Exception;

       public BbsVO select(int bbsno) throws Exception;

       public void update(BbsVO vo) throws Exception;

       public void delete(int bbsno) throws Exception;

      

}

 

자 그럼 Ibatis 라이브러리를 활용하여 구현을 해볼까요우선 공통적으로 Ibatis 환경설정 부분을 Abstract Class로 빼 보았습니다그냥 구현해도 되지만 확장성을 고려해서 빼보겠습니다.

package org.power.dao;

 

import java.io.IOException;

import java.io.Reader;

 

import com.ibatis.common.resources.Resources;

import com.ibatis.sqlmap.client.SqlMapClient;

import com.ibatis.sqlmap.client.SqlMapClientBuilder;

 

public abstract class AbstractIbatis {

      

       protected static SqlMapClient sqlMapper;

        

       static {

           try {

             Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");

             sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);

             reader.close();

           catch (IOException e) {

             // Fail fast.

             throw new RuntimeException("Something bad happened while building the SqlMapClient instance." + e, e);

           }

         }

 

}

 

SqlMapConfig.xml 환경설정 파일은 아래와 같습니다여기서 JDBC Connection 정보를 설정하는 곳이 보입니다.

, Ibatis JDBC를 쉽게 사용하기 위한 툴입니다여기서 확인해 두어야 할 것은 sqlMap 테그 부분으로 SQL문장을따로 xml형태로 읽어들여 사용한다는 것입니다.

 

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

<!DOCTYPE sqlMapConfig     

    PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"     

    "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

 

<sqlMapConfig>

 

             <transactionManager type="JDBC" commitRequired="false">

                           <dataSource type="SIMPLE">

                                        <property name="JDBC.Driver" value="oracle.jdbc.driver.OracleDriver" />

                                        <property name="JDBC.ConnectionURL" value="jdbc:oracle:thin:@127.0.0.1:1521:ORCL" />

                                        <property name="JDBC.Username" value="tony" />

                                        <property name="JDBC.Password" value="1234" />

                           </dataSource>

             </transactionManager>

 

             <sqlMap resource="BBS.xml" />

 

</sqlMapConfig>

 

BBS.xml의 내용을 보면 아래와 같다.

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

 

<!DOCTYPE sqlMap     

    PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"     

    "http://ibatis.apache.org/dtd/sql-map-2.dtd">

 

<sqlMap>

 

       <insert id="insertBBS" parameterClass="org.power.vo.BbsVO">

             <![CDATA[

                    INSERT INTO TBL_BBS (bbsno, title, content, writer, hits)

                    VALUES (SEQ_BBS_NO.NEXTVAL, #title#, #content#, #writer#, #hits#)

             ]]>

       </insert>

      

       <select id="selectBBS" resultClass="org.power.vo.BbsVO">

             <![CDATA[

                    SELECT bbsno, title, content, writer, hits, regdate

                    FROM TBL_BBS

                    WHERE bbsno = #bbsno#

             ]]>

       </select>

      

       <update id="updateBBS" parameterClass="org.power.vo.BbsVO">

             <![CDATA[

                    UPDATE TBL_BBS SET title=#title#, content=#content#,

                    writer=#writer#, hits=#hits#, regdate=#regdate#

                    where bbsno=#bbsno#

             ]]>

       </update>

      

       <delete id="deleteBBS" parameterClass="java.lang.Integer">

             <![CDATA[

                    DELETE FROM TBL_BBS WHERE bbsno=#bbsno#

             ]]>

       </delete>

      

</sqlMap>

SQL문이 기술되어 있습니다여기서 중요한 것이 ParameterClass resultClass입니다이는 Ibatis에서 SqlMapClient에서 매개변수로 넘기는 데이터 형태를 말합니다여기서 #bbsno#등과 같이 ## 묶여있는 것은 Ibatis에서 자동으로

맵핑을 시켜줍니다 SELECT문의 #bbsno# getBbsno() 메소드와 맵핑을 시킵니다그러므로 해당 필드들은 대소문자를 구분합니다.

 

 그럼 BbsDAOImpl 클래스를 한번 만들어보겠습니다.

package org.power.dao;

 

import org.power.vo.BbsVO;

 

public class BbsDAOImpl extends AbstractIbatis implements BbsDAO {

 

       @Override

       public void insert(BbsVO vo) throws Exception {

             sqlMapper.insert("insertBBS", vo);           

       }

 

       @Override

       public BbsVO select(int bbsno) throws Exception {

            

             return (BbsVO) sqlMapper.queryForObject("selectBBS", bbsno);

       }

 

       @Override

       public void update(BbsVO vo) throws Exception {

             sqlMapper.update("updateBBS", vo);

       }

 

       @Override

       public void delete(int bbsno) throws Exception {

             sqlMapper.delete("deleteBBS",bbsno);

            

       }

}

 

자 그럼 Junit을 통해 단위테스트를 해보겠습니다해당 코드는 아래와 기존과 동일합니다.

package org.power.test;

 

import org.power.dao.BbsDAO;

import org.power.dao.BbsDAOImpl;

import org.power.vo.BbsVO;

 

import junit.framework.TestCase;

 

public class BbsDAOTest extends TestCase {

 

       private BbsDAO bbsDao;

 

       protected void setUp() throws Exception {

             super.setUp();

 

             bbsDao = new BbsDAOImpl();

 

       }

 

       public void testInsert() {

 

 

             BbsVO vo = new BbsVO();

 

             try {

 

                    vo.setTitle("Ibatis사용 새로운 글을 등록합니다.(타이틀)");

                    vo.setContent("Ibatis사용  새로운 글을 내용을합니다.");

                    vo.setHits(100);

                    vo.setWriter("S002");

 

                    bbsDao.insert(vo);

 

             catch (Exception e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

             }

 

       }

 

       public void testSelect() {

 

             BbsVO vo = new BbsVO();

 

             try {

                    vo = bbsDao.select(200);

 

                    System.out.println(vo.getBbsno());

                    System.out.println(vo.getTitle());

                    System.out.println(vo.getContent());

                    System.out.println(vo.getWriter());

                    System.out.println(vo.getRegdate());

 

             catch (Exception e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

             }

 

       }

 

       public void testUpdate() {

 

             BbsVO vo = new BbsVO();

 

             try {

 

                    vo = bbsDao.select(300);

 

                    vo.setTitle("300  타이틀 수정입니다.");

                    vo.setContent("300  내용 수정한 내용입니다");

                    vo.setHits(0);

                    bbsDao.update(vo);

             catch (Exception e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

             }

       }

 

       public void testDelete() {

 

             try {

                    bbsDao.delete(150);

              catch (Exception e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

             }

       }

}

 

testInsert() 테스트 결과

testSelect() 테스트 결과

 

Ibatis를 테스트 할 경우 하나의 메소드만 테스트를 하여도 전체 xml을 테스트하므로 에러메시지를 확인하여야 합니다.

 

자 기존의 소스와 비교하였을 때 매우 간단하게 구현하는 것을 볼 수 있으며 보다 확장성이 좋아진 것을 볼 수 있습니다.

, SQL을 수정 또는 추가시 기존 소스를 수정해야 하는 부분이 많이 줄어 들었으며 결과를 return하는 것도 ibatis에서 자동으로 설정하여 반환하므로 개발자는 거의 신경을 안써도 됩니다.

 

그런데 만약에 여러게의 게시판이 있다고 생각해봅시다각 게시판마다 이런 동일한 코드를 작성해야 할 까요.

다음번에는 좀 더 확장성이 좋게 VO, DAO를 설계해 보도록 해보겠습니다.

[출처] http://blog.naver.com/byebird

'Programming > Java' 카테고리의 다른 글

Generic을 사용한 VO, DAO의 구현  (0) 2011.07.19
JDBC를 이용한 VO,DAO의 구현  (0) 2011.07.19
Posted by 그리브스
, |

최근에 달린 댓글

최근에 받은 트랙백

글 보관함