2014.09.16 18:23

내 명함








Trackback 5 Comment 0
2014.07.09 23:14

myBatis에서의 동적쿼리 - 1. foreach




iBatis에서의 습관을 버리고 myBatis로 옮겨올  시기가 된듯합니다.

Spring3.2에서도 iBatis는 deprecated 되어 더이상 myBatis로 옮기는데 주저할수는 없는 현실이 되어버렸습니다.

 

오늘은 예전 iBatis에서 iterate 문으로 사용했던 부분을 forEach로 변경하는 테스트를 시험삼아 해보았습니다.

myBatis를 쓰면서 느끼는것은 이제 xml문법스타일은 버려도 되겠구나 하는 것입니다.

 

foreach

동적 SQL 에서 공통적으로 필요한 것은 collection 에 대해 반복처리를 하는 것이다. 종종 IN 조건을 사용하게 된다. 예를 들면,

<select id="selectPostIn" resultType="domain.blog.Post">
  SELECT *
  FROM POST P
  WHERE ID in
  <foreach item="item" index="index" collection="list"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>

foreach 요소는 매우 강력하고 collection 을 명시하는 것을 허용한다. 요소 내부에서 사용할 수 있는 item, index 두가지 변수를 선언한다. 이 요소는 또한 열고 닫는 문자열로 명시할 수 있고 반복간에 둘 수 있는 구분자도 추가할 수 있다.

참고 파라미터 객체로 MyBatis 에 List 인스턴스나 배열을 전달 할 수 있다. 그렇게 하면 MyBatis 는 Map 으로 자동으로 감싸고 이름을 키로 사용한다. List 인스턴스는 “list” 를 키로 사용하고, 배열 인스턴스는 “array” 를 키로 사용한다. 

 

 

 

위의 내용은 myBatis 한국어 사이트 번역판에 설명되어진 것입니다만 사실 제대로된 설명이라고 하기엔, 특히나 개발감각 없는 저 같은 개발자에겐 한방에 와닿지 않습니다.

 

그저 따라하기 예제 샘플이 최고입니다.

 

User.java

public class User {

  private int userIdx;

  private String userName;

  private Integer [] userIdxArray;

  private List<Company> compList;

  public ... 이하는 getter, setter 메소드이므로 생략.

 

 

}

 

 

1. 배열을 파라메터로 전달하여 foreach문을 사용하는 예

UserMapper.xml

<select id="getUserListByUserIdxArray" resultMap="User-Result" parameterType="User">

  SELECT

           USER_IDX as "userIdx"

, USER_NAME as "userName"

  FROM USER

  <trim prefix="WHERE" prefixOverrides="AND|OR">
         <if test="userIdxArray  != null">
           AND USER_IDX IN (
              <foreach collection="userIdxArray" item="a" separator=",">#{a}</foreach>
          )
        </if>
 </trim>

 

</select>

 

 

WHERE 문이 오는 곳에 위치한 trim  도 iBatis에는 없던 myBatis에서 새로이 추가된 구문입니다. 보통 꼼수(?)로

WHERE  1=1

위와 같이 사용하던 부분인데, 이러한 꼼수를 쓰지말라고 제공하는 구문이라고 생각합니다.

보통 if 문을 사용하는 곳 앞부분에 추가하는데, 이전 iBatis에서는 <dynamic...> 이란 구문이 아마 이에 해당했던 걸로 기억합니다.

 

- collection : 말 그대로 collection 객체들이 오는 곳입니다.

- item : Collection 객체들의 instance? 라고 할수 있습니다.  jstl에서의 forEach를 예로 들면 "var"에 해당하는 놈이라고 할수 있겠네요. 처음엔 글자가 jstl의 items와 비슷해서 같은걸로 이해했었습니다.

- separator : 구분자.

 

배열이기 때문에 이 alias를 그대로 넣어주면 쿼리에 적용됩니다. 

 

2. ArrayList를 파라메터로 전달하여 foreach문을 사용하는 예.

 

...

      <if test="compList  != null">
           AND COMP_NAME IN (
              <foreach collection="compList" item="a" separator=",">#{a.compName}</foreach>
          )
      </if>
... 

 

 

배열 사용법과 별 차이는 없습니다.

 

이전 iBatis를 사용할때는 array 객체가 필요할때는 이상하게 꼭 hashmap 객체에 넣어서 보냈던 기억이 있습니다. POJO 에 넣어서 보내면 뭔가 모르게 오류가 나서 잘 안되던 기억이 있었는데(어쩌면 사용법을 틀려서 그런걸수도 있겠지만), myBatis 에 와서는 그런부분이 없습니다. 좀더 명확해졌다고 해야할까요?

 

오늘은 myBatis의 foreach문을 통한 반복문 사용법을 테스트 해보았습니다.

 

끝.


출처 : http://gubok.tistory.com/386

Trackback 6 Comment 1
2014.05.09 11:34

Tomcat Context Reloader




Tomcat의 컨텍스트를 reloadable=“false”인 상태에서, Tomcat Manager를 설치하지 않은 상태에서 수동 Reload 할 수 있는 Valve를 만들어 보았다. Reload Tomcat Context manually(without manager or reloadable=“true” option).

설정

  • Tomcat Reload Valve 소스와 Jar 파일에서 tomcatreloadvalve.jar 파일을 $CATALINA_HOME/lib 로 복사한다.
  • server.xml 혹은 context.xml의 <Context> 항목에 Valve를 추가한다. 항상 <Context> 항목에만 추가해야 한다.
    <Context docBase="some" path="/some" reloadable="false" >
        <Valve className="kr.pe.kwonnam.tomcat.reloader.TomcatReloadValve"/>
    </Context>
  • reloadable=“false”로 둔다. 원래 이 Valve의 목적은 자동 Reloading을 끄고, 항상 수동으로 원하는 경우에만 Reloading하는 것이다.

실행

  • 웹브라우저 혹은 wget 등으로 http://localhost:8080/reloadContext 를 호출한다.
  • 실제 URL의 도메인네임 부분은 자신의 톰캣 설정을 따른다.
  • “Context Reloaded!!” 메시지가 나오면서 Reloading이 완료된다.

소스

package kr.pe.kwonnam.tomcat.reloader;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
 
import org.apache.catalina.Container;
import org.apache.catalina.Context;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.valves.ValveBase;
 
/**
 * Reload Tomcat Context by requesting URL
 *
 * Context의 reloadable="false"인 상태에서도 /reloadContext URL을 호출하면 해당 컨텍스트가 Reloading 된다.
 *
 * @author 손권남 kwon37xi@gmail.com
 *
 */
public class TomcatReloadValve extends ValveBase {
 
	private static final String RELOAD_CONTEXT_URI = "/reloadContext";
 
	@Override
	public void invoke(Request request, Response response) throws IOException,
			ServletException {
 
		Container container = getContainer();
 
		String requestUri = request.getRequestURI();
 
		String reloadUri = request.getContextPath() + RELOAD_CONTEXT_URI;
 
		if (requestUri.startsWith(reloadUri)
				&& container instanceof Context) {
			reloadContext(response, container);
			return;
		}
 
		getNext().invoke(request, response);
	}
 
	private void reloadContext(Response response, Container container)
			throws IOException {
		((Context) container).reload();
		HttpServletResponse httpResponse = response.getResponse();
 
		httpResponse.setContentType("text/plain;charset=utf-8");
		httpResponse.getWriter().write("Context Reloaded!!");
		httpResponse.getWriter().close();
 
		return;
	}
 
}

 

http://kwonnam.pe.kr/wiki/java/tomcat/contextreload


Trackback 3 Comment 0


티스토리 툴바