진행하고 있던 프로젝트에 MyBatis를 적용하다가 에러가 나서 정리해 둔다.


발생한 에러는 아래와 같다.


* 에러 메세지


 심각: Servlet.service() for servlet [action] in context with path [/xxx] threw exception [Request processing failed; nested exception is        

        org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: 

        ### Error querying database.  Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for 

        xxxMapper

        ### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for 

        [xxxMapper] with root cause

       java.lang.IllegalArgumentException: Mapped Statements collection does not contain value for 

        xxxMapper

 ** 위의 메세지 중 프로젝트 명이 표기되는 부분은 xxxMapper로 바꾸어 표기했다. 



* 원인


    : 위와 같은 에러가 발생할 경우 아래와 같이 여러 원인이 존재할 수 있다고 한다. 

     (1) mapper id가 틀린 경우

     (2) Parameter와 bean의 field명이  틀린 경우

     (3) sql.xml에서 정의된 namespace와 DAO에서 호출하는 namespace가 다를 경우

     (4) mapper가 정의가 되어 있지 않거나 Spelling이 틀린 경우

     (5) mapper에 정의된 namespace 명칭이 같은 Application 내에 중복 될 경우



* 해결


   : 나의 경우엔 4번이 원인이었다. Mapper 파일 명시 할 때 대소문자 구분을 하지 않아 mapper 파일을 못찾으면서 발생한 에러였다.

   : mapper 파일 명시했던 설정 파일 보면 mapperLocation 속성에 *_maria.xml 파일이라 명시되어 있다.


     -->  context-datasource.xml 파일 내 설정(AS-IS)


  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

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

      <property name="configLocation" value="classpath:/mybatis/mybatis-config.xml" />

      <property name="mapperLocations">

   <value>classpath:/mapper/**/*_maria.xml</value>

      </property> 

  </bean>



    : 해당 mapper 파일은 실제로 *_Maria.xml 파일이기 때문에 대소문자 수정이 필요하다 ㅎㅎㅎㅎ 이런 실수는 다음엔 하지 말기


   

  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

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

      <property name="configLocation" value="classpath:/mybatis/mybatis-config.xml" />

      <property name="mapperLocations">

   <value>classpath:/mapper/**/*_Maria.xml</value>

      </property> 

  </bean> 


   : 위와 같이 오타를 수정하고나서 다시 돌려보니 이제 제대로 mapper 파일을 찾았다 ㅎㅎ 


    내경우 말고도 위의 에러 원인 가능한 5가지 경우는 주의해야겠다. 



__________________________________________________________________________________________________________________________________________________________

** 본 포스팅에 대해 수정해야할 부분이나 추가 의견 등이 있으신 분들은 댓글 달아주세요. 언제나 환영입니다 :) 

** 본 포스팅을 reference 자료로 참고하실 분들은 출처를 꼭 밝혀주시기 바랍니다.


  


정신이 없어 캡처 이미지를 뜨지 못했다.. 

그래도 꽤 자주 발생하는 에러인것 같아 글로라도 정리해놔야겠다.


SVN에서 maven 프로젝트를 처음 체크아웃 받을 때 가끔 JSP 파일들에만 빨간색으로 에러가 쭈~욱 뜰 때가 종종 있다.

체크아웃밖에 안했는데 에러가 나서 당황스러웠지만 찾아보니 원인과 해결방법은 아래와 같았다.


우선, 


 * 에러 메세지: javax.servlet.jsp.JspException cannot be resolved to a type 

 * 원인: 프로젝트를 처음 만들면서 target runtime을 선택하지 않아 발생된 문제다.

          일부 공통컴포넌트의 경우는 JSP나 Servlet에 대한 참조가 필요한 경우가 있다. (taglib를 사용하기 위해)

          이 경우는 Server Runtime(ex: Apache Tomcat 등)에 대한 library 참조가 필요하다.


* 해결1: project 우클릭 > build path > configure build path > library 탭 > add library 선택 > Server Runtime 선택 > 설정되어 있는 

           Servlet engine 선택!


* 해결2: project 우클릭 > properties > project facets > 오른쪽 Runtime에 사용하는 was 서버 선택! > project clean 



해결 끝~~~~~!



__________________________________________________________________________________________________________________________________________________________

** 본 포스팅에 대해 수정해야할 부분이나 추가 의견 등이 있으신 분들은 댓글 달아주세요. 언제나 환영입니다 :) 

** 본 포스팅은 아래의 reference 들을 참고하여 내용을 덧붙인 글입니다. 혹시, 문제가 되는 경우 알려주시면 조치하도록 하겠습니다.

** 본 포스팅을 reference 자료로 참고하실 분들은 출처를 꼭 밝혀주시기 바랍니다.


  - http://aljjabaegi.tistory.com/187

  - http://open.egovframe.go.kr/nforges/freediscussion/qna/4327/.do


'UX' 카테고리의 다른 글

[WebSquare5] 웹스퀘어5 연동  (0) 2017.04.29
AJAX 통신 기초  (0) 2017.02.26
jQuery 기초  (0) 2017.02.26
Javascript 기초2  (0) 2017.02.26
Javascript 기초  (0) 2017.02.26

카테고리에 정확히 부합하는 글은 아니지만 우선 여기에 올려야겠다 ㅎㅎ

용학 차장님한테 혼난 후에, 차장님이 메신저로 보내주신 파일 '좋은 프로그래머가 되는 법'.


1부터 10까지 전부 나한테 부족한 면들이라 너무 와닿았다. 내 부족한 면에 대해 많은 고민을 한 뒤라 정말 한 구절 한 구절 생각해보게 되었다.


기억하고 실천해야지 :)


________________________________________________________________________________________________________________________________


[ 좋은 프로그래머가 되는 법 ]


 1.꾸준히 한다. 

   -프로그램이 언어도 언어라서, 하루에 몰아서 하는 것보다 매일 꾸준히 하는 것이 중요하다.

    경력이 많은 프로그래머들도 몇달만 코딩을 안해도 감이 많이 떨어지는 것을 느낀다.

 

   -특히 프로그래밍을 처음 배우는 사람이라면, 꼭 컴퓨터 앞에 않지 않더라도 책을 항상 가까이해서 문법 및 표현에 익숙해지도록

    하는거이 중요하다. 자주보는 것이 중요하다.


2. 반복해서 한다. 

  -단지 태권도 교본을 잘 이해했다고 해서 멋진 발차기를 기대할수 없는 것처럼, 책의 내용을 잘 이해했다고 해서 하루아침에

   프로그래밍을 잘 할 수 있는 것은 아니다.

 

  -이해한 내용을 바탕으로 수많은 반복연습을 통해서만 지식을 진정한 자신의 것으로 만들 수 있다. (같은 예제를 공부하더라도

   이리저리 조금씩 변경해서 공부하는 것이 좋다.)

 

  -처음 2~3번은 자세히 보고, 그 다음 부터는 하루에 10분간 10페이지를 훑어보는 식으로 반복하자.

   몇달안에 책에 있는 모든 목차와 예제의 위치와 주요 내용을 모두 파악할수 있을 것이다.(적어도 언어책 한권, 데이터베이스책한권

   정도는 이렇게 할 필요가 있다)


3. 좋은 코드를 많이 보고 따라한다. 

  -이미 수많은 선배들이 여러문제들에 대한 코딩을 다 작성해 놓았다. 새로운 방법으로 문제를 풀겠다고 도전하는 것은 별 의미가 없다.

   "이럴때는 이렇게 하는 구나..."라는 것을 배우고 유사한 상황에서 활용하면 되는 것이다. 여러분들이 해야할일은  이러한 경험들을 많이

   쌓아 나가는 일이지, 기존과는 다른 새로운 코딩방식을 만들어 내는 것이 아니다.

 

  -좋은 코드는 보기에도 좋다. 잘 정리되어 있고, 별로 특별한 것이 없다. 프로그래밍의 각 요소들을 잘 이해하고, 각 요소들을 적재적소에

   바르게 사용하면 되는 것이다. 단지 소스의 라인수를 줄인다고해서 좋은 코딩이 아닌것이다. 로직이 소스코드에 잘 드러날수 있게 쉽고

   평범하게 작성하는 것이 좋은 코드인 것이다. 이창호의 바둑이 평범하듯이...

 

4. 기본에 충실한다. 

  -빨리 프로그래밍을 배워서 뭔가 해보고 싶은 여러분들의 마음을 이해하지 못하는 것은 아니다.

   그러나. 프로그래밍 하루 이틀 할 것도 아니고,. 처음에 기본을 잘배워놓지 않으면 , 그 이후에는 기회가 잘 없다. 실무에서는 매일 개발하기

   바쁘고 , 새로운 기술 배우기 바쁘고...


5. 코드를 작성하기 전에 순서도를 그린다. 

  -"프로그램이 = 코딩 "이 아니라 "프로그래밍 = 로직설계 +코딩"이다. 필자가 생각하는 로직 설계와 코딩간의 비율은 8:2 정도이다.

 

  -포토샵만 잘한다고 디자이너가 아니라는것은 여러분들도 잘~알고 있을 것이다. 새로운 기술이나 프로그램을 공부하는 것도 중요하지만,

   어떤 과제가 주어졌을때 이를 잘 분석하고 설계하는 능력을 장기적으로 키워나가도록 노력해야할 것이다,(다양한 주제에 대해서 문제를

   풀어보고 다양한 종류의 책을 읽자.)

 

  -문제를 구성하고 있는 주인공들을 찾아서 나열해보라, 그리고 이들간의 관계는 무엇이고, 규칙은 무엇인 적어보라,(머릿속으만 생각하지 말고!)

 

6. 주석을 가능한한 많이 적는다.

 

  -주석은 매우 유용하고도 중요한 요소이다. 그럼에도 불구하고 많은 사람들이 이를 소홀히 한다.

   자신이 작성한 코드도 몇일만 지나면 이해가 안되는 경우가 많다. 적어도 이해하는데 시간이 걸린다. 주석은 이러한 시간들을 절약해줄것이며,

   보다 에러가 적은 코드를 작성하는데 도움을 줄 것이다. 특히 여러사람이 공동작업을 하는 경우에는 더욱 더 중요하다. 서로를 위해서..

 

  -작업과 관련된 가능한한 많은 정보를 주석에 담도록 하자.


7. 작업일지를 작성한다.

 

  - 과학자들이 매일 연구한 내용을 일지로 적듯이 여러분들도 일지를 적어보자. 오늘은 이렇게 저렇게 해봤는데 잘 안되었다. ...

    xxx.java의 코드를 이렇게 바꾸었다. 몇시몇분에 xx로 백업받아 놓았다...라는 식으로 가능한 자세히 적도록 한다. 이렇게 함으로써

    여러분들의 경험을 기록으로 쉽게 보관할수 있으며, 문제해결에 많은 도움이 된다.


 

 8. 자신의 소스를 가꾼다.

 

  -보통 코딩을 마치고 나면, 모든 것을 덮어두곤 한다. 원하는 결과를 얻었다고 거기서 그치지 말고 이제 로직과 코드를 보다 효율적으로

   개선할 벙법이 없는지 고민해보자. 글을 써놓고 좋은 글로 만드릭 우해 읽고 또 읽고 다듬듯이 코드를 다듬어보자. 여러분들의 코드를

   구사하는 능력이 보다 향상되어가는것을 느낄 수 잇을 것이다.

 

  -여러분들을 위한 제안을 작은 프로그램을 만들어서 오랜기간동안 점차 발전시켜 나가는 것이다. 새로운 기능들을 하나씩 추가해가고,

   기능을  발전시켜나가보자. 이 과정을 통해서 여러분들의 실력은 몰라보게 향상될 것이다.


 

 9. 생각하라.

 

  - 항상 머릿속에 한 가지 문제를 준비하라. 지하철을 기다리는거나, 화장실에서 볼일 볼때 문제를 풀어보자.



10. 좋은 책을 선택한다.

 

  -공부를 시작할때 제일 먼저 하는 일은 아마도 책을 고르는 일일 것이다. 보통 책하나에 수십시간을 학습하게 되는데. 책을 잘못선택한

   경우 수십시간과 노력을 허비하는 셈이다. 바른 책을 고르는 일은 쉬운일이 아니지만, 최소한 몇 시간을 투자해서 최선의 선택을 하도록 노력해야 수십시    간을 허비하는 일이 없을 것이다.

 

  -책을 고르는 법은 여러가지가 있겠으나, 가장 중요한 것은 본인이다. 서점에서 같은 종류의 몇가지 책을 놓고 서로 비교해보면, 시간을 들인

   만큼 보다 나은 선택을 할 가능성이 높아진다.

 

  -많은 컴퓨터 서적이 독자들의 선택을 어렵게 하고, 컴퓨터 업계 특성사 좋은책을 만들기 보다 빨리 찍어서 파는 것이 더 중요해진 요즘.

   독자들의 바른 선택이 보다 나은 책이 출판되는 것을 가능하게 한다는 것을 알았으면 한다.



▶ 리팩토링(Refactoring) 


1. refactoring 이란?

     * 리팩토링은 외부 동작을 바꾸지 않으면서 내부 구조를 개선하는 방법으로, 소프트웨어 시스템을 변경하는 프로세스다.

     * 디자인을 먼저 한 후 코드를 만드는 것이 아니라 일단 돌아가는 코드를 작성하고, 그 후에 그 코드가 더 좋은 구성을 갖도록 바꾼다는 것.

     * 여러 곳에 산재된 중복 코드 정리 

     

 2. refactoring 하는 이유?

     * 코드 간결성 및 가독성 증대

     * 무엇인가 소스의 변경이 필요할 때(기능 추가나 삭제,수정 작업이 일어날 때) 소스의 리팩토링은 포장이사처럼 편하게 작업하도록 도와준다.

     * 리팩토링은 소스의 중복된 부분을 모듈화 시켜준다. 모듈화는 입출력이 명확하기 때문에 이식성을 높여준다. 

     * 리팩토링을 통해 시스템 복잡도를 줄일 수 있다. 

     

 3. 활용

     * coffeeList 조회 결과 coffee1 값이면 아메리카노, coffee2 값이면 카페라떼를 반환해주는 로직

     * 기존: OriginalImpl.java 클래스 내 메소드 selectMenuList(), selectMenu(), updateMenu() 등에 소스 반복

     * 활용: 여러 메소드 내에 반복되는 소스를 리팩토링 하여 하나의 메소드로 생성(convertCoffee(resultMap))

                            

@Service("originalService")

public class OriginalImpl implements OriginalService {


    public static final String AMERICANO = "coffee1";

    public static final String CAFELATTE= "coffee2";

    public static final String AMERICANO_VAL = "아메리카노";

    public static final String CAFELATTE_VAL= "카페라떼";

    

    // 메뉴리스트 조회

    public List<Map<Stirng, Object>> selectMenuList() throws Exception {

   

        ......


        List<Map<Stirng, Object>> resultList= originalDaoImpl.selectMenuList();

        String coffee= resultList .get("coffee").toString();

        

        if(coffee.equalsIgnoreCase(AMERICANO)) {

            coffee = AMERICANO_VAL;

        } else if (coffee.equalsIgnoreCase(CAFELATTE)) {

            coffee = CAFELATTE_VAL;

        } else {

            throw new DataFormatException(); 

        }


        resultList.put("coffee", coffee);


        ......


    }

      

    // 메뉴 조회

    public Map<String,Object> selectCoffee() throws Exception {


        ......

     

     Map<String,Object> resultMap =  originalDaoImpl.selectMenu();


     String coffee= resultMap .get("coffee").toString();

         

        if(coffee.equalsIgnoreCase(AMERICANO)) {

            coffee = AMERICANO_VAL;

        } else if (coffee.equalsIgnoreCase(CAFELATTE)) {

            coffee = CAFELATTE_VAL;

        } else {

            throw new DataFormatException(); 

        }


        resultList.put("coffee", coffee);


        ......


    }



   // 메뉴 업데이트

    public Map<Stirng, Object> updateMenu() throws Exception {

         ......


     // 메뉴 업데이트 후 메뉴 조회 서비스 (업데이트 반영)

     Map<String,Object> resultMap =  originalDaoImpl.selectMenu();


     String coffee= resultMap .get("coffee").toString();

         

        if(coffee.equalsIgnoreCase(AMERICANO)) {

            coffee = AMERICANO_VAL;

        } else if (coffee.equalsIgnoreCase(CAFELATTE)) {

            coffee = CAFELATTE_VAL;

        } else {

            throw new DataFormatException(); 

        }


        resultList.put("coffee", coffee);


        ......


   }



위의 코드에 주황색으로 표시 된 부분이 여러 method에서 반복되고 있는 소스다. 


반복되는 소스는 시스템 복잡도를 높일 뿐만 아니라 소스에 변경사항이 발생하는 경우 해당 소스를 포함하고 있는 각 메소드 마다

일일이 수정해줘야하는 번거로움이 생긴다. 


이러한 문제를 해결하기 위해 아래와 같이 리팩토링을 한다.


   * 반복되는 소스 전체 선택 후 우클릭 > Refactor > Extract Method 선택

   * Method 명 설정









 // extract method 결과 - convertCoffee(Map<String, Object> resultMap) 생성

   private void convertCoffee(Map<String, Object> resultMap) throws DataFormatException {

       String coffee= resultMap .get("coffee").toString();

     

       if(coffee.equalsIgnoreCase(AMERICANO)) {

     coffee = AMERICANO_VAL;

} else if (coffee.equalsIgnoreCase(CAFELATTE)) {

             coffee = CAFELATTE_VAL;

        } else {

     throw new DataFormatException(); 

}


        resultMap.put("coffee", coffee);

 } 



 // 메뉴리스트 조회

    public List<Map<Stirng, Object>> selectMenuList() throws Exception {

        ......


        List<Map<Stirng, Object>> resultList= originalDaoImpl.selectMenuList();

        resultList = convertCoffee(resultList);

        ......

   }



// 메뉴 조회

   public Map<String,Object> selectCoffee() throws Exception {

        ......

     

       Map<String,Object> resultMap = originalDaoImpl.selectMenu();

       resultMap = convertCoffee(resultMap);

        ......

   }



 // 메뉴 업데이트

    public Map<Stirng, Object> updateMenu() throws Exception {

         ......


     // 메뉴 업데이트 후 메뉴 조회 서비스 (업데이트 반영)

     Map<String,Object> resultMap =  originalDaoImpl.selectMenu();

     resultMap = convertCoffee(resultMap);

        ......

   }



convertCoffee 라는 method를 생성함으로써 각 method에서는 얘를 호출하여 coffee 명을 가져올 수 있게 된다.


기존 코드보다 훨씬 간결해진 모습을 확인할 수 있다. (주황색 부분이 파란색 부분으로 변경됨!)


나같은 경우도 처음에는 각 method마다 동일 소스를 계속 반복하여 사용했었다..'재활용성'에 대한 개념이 아예 없었다. 

다행히 리팩토링은 처음부터 적용하려는 의도로 나온 애가 아니라, 소스코드 작성 후 코드 품질 최적화를 위해 

적용할 수 있는 부분에 쓰는 애다. ㅎㅎ  물론 미리 알고 썼더라면, 리팩토링하는 시간도 줄었겠지만.... 앞으로 잘쓰면 되지~~


처음엔 반복되는 코드를 작성했었더라도 이제 리팩토링 개념과 효과를 알았으니 내 코드 최적화를 위해 

리팩토링을 요리조리 잘 써먹어야 겠다. 


이번 포스팅에는 리팩토링의 정말 기본 내용만 담고 있지만, 앞으로 리팩토링 해보면서 좀 더 깊이 있게 쓰게되면

리팩토링 2.0 버전으로 새 글 리포팅해야겠다 :) 


__________________________________________________________________________________________________________________________________________________________

** 본 포스팅에 대해 수정해야할 부분이나 추가 의견 등이 있으신 분들은 댓글 달아주세요. 언제나 환영입니다 :) 

** 본 포스팅은 아래의 reference 들을 참고하여 내용을 덧붙인 글입니다. 혹시, 문제가 되는 경우 알려주시면 조치하도록 하겠습니다.


  - http://belong2jesus.tistory.com/62

  - http://www.zdnet.co.kr/news/news_view.asp?artice_id=00000039161606&type=det&re= 

  

'JAVA' 카테고리의 다른 글

예외처리 관련 참고문서  (0) 2017.06.11
로깅(Logging) 참고문서  (0) 2017.06.11
JAVA - 향상된 for 문 (from Java1.5)  (0) 2017.02.26
system32와 systemWOW64  (0) 2017.02.26
SAPJCO 연동 설정  (0) 2017.02.26

+ Recent posts