[Mybatis] 쿼리에서 특정 문자 제거(if 사용 시) iBatis/MyBatis

쿼리를 쓸 때 조건절을 동적으로 사용하는 경우가 많다.

그럴 때 문제가 되는게 연산자나 콤마의 제거이다.


그럴 때는 Mybatis의 trim 을 쓰면 된다.

두가지의 예를 들어보겠다.



1. 맨 끝에 있는 콤마(,)를 제거하는 경우


<update id="updateAuthorIfNecessary" parameterType="domain.blog.Author">
UPDATE AUTHOR
<trim prefix="SET" suffixOverrides=",">
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio},</if>
</trim>
WHERE id=#{id}
</update>


맨앞에 SET을 붙이고 if안에 무엇이 들어가도 맨 끝에 있는 콤마를 지우겠다는 것이다.



2. 맨 앞에 있는 연산자를(AND 또는 OR) 제거하는 경우

<select id="selectInfo" parameterType="domain.blog.Author" resultType="authorResultMap">
 SELECT * FROM AUTHOR
 <trim prefix="WHERE" prefixOverrides="AND |OR">
<if test="username != null>AND username=#{username}</if>
<if test="password != null>OR password=#{password}</if>
<if test="email != null>AND email=#{email}</if>
</trim>
</select>


요번에는 앞에 들어가는 AND 또는 OR을 제거하겠다는 것이다.

AND | OR 이건 안써봤지만 MyBatis3 User Guide를 보니 그렇게 나와있넴~



[Java] Custom Annotation 만들기 응용 (Spring AOP 이용한) JAVA

사용자가 만들어 사용하는 Custom Annotation은 어떻게 효과적으로 응용할 수 있는지 궁금할 것이다.
인터넷에 예제도 별로 없고.. 
내가 짠 것은 아니지만, Spring 프렘웍의 AOP를 이용해서 만든 커스텀 어노테이션 사용법에 대해서 정리하겠다



* AOP(Aspect Oriented Programming)이란?

먼저, OOP(Object Oriented Programming)의 경우, 객체 단위로 기능을 묶어서 코딩하는 방법이다.
그러나 실무에서는 이런 구현방법이 단점이 될 수 있다. 
사용자 인증을 항상 해야 한다고 하면, 객체마다 반복되는 코드가 생기게 될 것이다. 
 
그래서 사용자 인증 같이 자주 사용되는 코드를 단위로 묶어서 필요할 때마다 삽입하여 사용하는 것을 AOP 라고 한다.
사용자 인증하는 코드가 A라고 하고, 비지니스 부분을 B라고 한다면 
[B가 실행되기 전 또는 후에 A를 실행한다.]  
전체적으로는 위의 코드가 한 비지니스 로직에서 실행되는 것처럼 하는 것이다.




컨트롤러 타기전에 사용자 인증 하는 예제이다.


(1) 커스텀 어노테이션 설정


1. 어노테이션 인터페이스 작성


@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.Method)
public @interface PreAuth {
// Auth는 enum 임
Auth hasAuth() default com.x.x.Auth.VISITOR;  // 어노테이션 속에 값이 없다면 디폴트로 VISITOR로 지정
}


*******************************************

@Retention : 어노테이션은 주석이기 때문에 컴파일시 사라진다. 하지만 retention을 통해, 런타임때까지 주석을 남기겠다 라고 컴파일러에게 알려줌

@Target : 어디에 어노테이션을 적용할 지 타겟을 정함


retention에도 옵션이 많고, 이 어노테이션들 말고 옵션이 더 있지만 그건 찾아보면 나온당ㅋㅋ



2. Auth enum 구현


public enum Auth {
ADMIN(1), OWNER(2), USER(3), VISITER(4);
// 생략
}


*********************************************

숫자로 처리하기 위해 enum 사용.



3. 비지니스에서의 어노테이션 사용


@Controller
public class Text {
      @PreAuth(hasAuth=Auth.OWNER)    
public void view() {
// 비지니스 구현
}
}



(2) AOP  


1. AOP 사용을 위한 xml 설정 (*-context.xml)


....
<aop:aspectj-autoproxy />



**********************************************

저 설정을 등록하면 @Aspect 어노테이션을 사용할 수 있다.




2. 인증 처리 구현


@Component
public class AuthManager {
// 인증 처리 구현 
}



3. (2)2번에서 구현한 로직을 (1)3 에 삽입할 시점 구현(Aspect)


@Aspect
@Component
public class AuthAspect {
@Resource(name = "authManager")
AuthManager authManager;

@Pointcut("@annotation(com.x.x.annotation.PreAuth)")  // @PreAuth가 있는 지점을 pointcut으로 지정
public void pointcut() { } 

@Before("pointcut()")   // pointcut 한 부분 이전에, 인증 수행(joinpoint)
public void beforeTargetMethod(JoinPoint joinPoint) {
hasAuth(joinPoint);
}

private void hasAuth(JoinPoint joinPoint) {

// Todo: reflection을 이용하여 어노테이션 속에 있는 값을 가져온다
authManager.hasAuth(hasRole); // 위에서 받아온 값을 넘긴다. 
}
}


**********************************************

joinPoint : 메소드 호출 전/후 등의 적용 지점

pointcut : 실제 로직에 적용되는 joinpoint




※ 잘못 설명한게 있으면 지적 부탁드림




[JSTL] 수동 tag 라이브러리 만들기 JAVA

옛날엔 태그라이브러리를 사용하기 귀찮고 복잡?했다고 한다
지금은 간단히 쓸 수 있도록 JSTL이 업데이트 됐다.

사용법 두 가지를 설명하겠다.


1.  태그 안 속성에 따라 값이 출력되는 것,
(<custom:test returnColumn="name" id="${test.id}" /> 이런 태그를 쓰면 값이 출력되는 것)

2. 위와같이 태그를 쓰면 태그 안 속성에 따라,  attribute에 set되서 EL태그로(${test.id}) 쓸 수있는 예제이다.







1. 템플릿 단  (jsp)


test 객체의 id값으로 name을 받아오는 예제이다.



... 태그라이브러리들 생략
<% taglib prefix="custom" tagdir="/WEB-INF/tags" %>    -- 태그파일(.tag) 가 위치할 디렉토리를 쓴다

첫번째 방법 : <custom:test returnColumn="name" id="${test.id}"  />    -- tag파일에서 계산된 값이 출력될 것임.
두번째 방법 : <custom:test returnColumn="name" id="${test.id}" var="value" />    
${value.name}       

-- 두번째 방법 사용 후 ${value.name} 이렇게 쓸 수 있는 것은,  tag 파일에서 attribute에 set을 해주기 때문이다
-- var 속성에 넣은 이름이 객체명이 될 것이다



***********************************************************************

custom : prefix
test : 태그 파일 이름 (여기서는 /WEB-INF/tags/test.tag 이다)
returnColumn, id, var : 일반적인 태그에 들어가는 속성처럼 속성 이름이다. 이 이름은 tag 파일에서 지정하게 된다.
${test.id} : 현재 페이지를 보여줄 컨트롤러, 서비스 등 에서 넣은 모델 값(이 값이 jsp에 오는 과정은 생략)
${value.name} : ${test.id} 처럼, 태그파일 안에서 var속성에 지정된 value 란 곳에 값을 넣어준다.(tag파일에서 넣어 주는 것임)



2. tag 파일 (test.tag)

로직은 보지말고 사용법만 보자.



<%@ tag body-content="empty" pageEncoding="UTF-8"%>
<%@ tag import="org.springframework.web.context.WebApplicationContext,
                    org.springframework.web.servlet.support.RequestContextUtils,
                        com.test.service.TestService" %>

<%@ attribute name="returnColumn" required="true" %>
<%@ attribute name="id" required="false" %>
<%@attribute name="var" required="false
" %>
<%
    // bean을 가져온다
    WebApplicationContext ctx = RequestContextUtils.getWebApplicationContext(request, request.getServletContext());
    TestService testService = (TestService) ctx.getBean("testService");
    Object returnValue = null;

    if (returnColumn.equals("name")) {
        returnValue = testService.getId("name");  // 로직 처리
     }

    if (null != var) {
        ctx.getServletContext().setAttribute(var, returnValue);  // 두번째 방법 - attribute에 set 한다
    } else {
        out.print(returnValue);   // 첫번째 방법 - 출력해버린다
    }
%>




3. 결과


첫번째 방법 : 김남길    -- 태그를 쓰기만 하면 값이 출력 된다
두번째 방법 : 김남길     -- 태그 사용 후 value 객체에 값이 들어가게 되고, ${value.name} 처럼 사용해야 값이 출력 된다.



[Spring] cookie에 값을 넣지 못하는것 Spring Framework

컨트롤러에서 쿠키에 값을 집어넣으려고
response.addCookie(쿠키이름, 값); 을 해도 JSESSION만 생길뿐,
내가 설정한 쿠키이름으로 set이 되지 않았다.

* JSESSION이란 - 클라이언트가 서버에게 요청을 보낼 때, 어떤 클라이언트인지식별하게 해주는 것 이다.
즉, 서버에서 기본적으로 생성해주며, 값은 유일한 값으로 해시코드로 들어있다.



스프링에서는 컨트롤러에 저런식으로 쿠키를 넣는것이 안된다고함.
대신 인터셉터에서는 사용가능 함. 

듣기로는 컨트롤러에서 domain, path 설정을 하면 돌아간다고 하는데
그래도 안되는 것 같고,

그래서 결국 CookieGenerator 클래스를 이용해서


CookieGenerator cg = new CookieGenerator();

cg.setCookieName("쿠키이름");
cg.addCookie(response, 값);


하니까 잘 저장되었다. domain이나 path설정을 안해도 말이다.


이 클래스에 대한 레퍼런스는
http://static.springsource.org/spring/docs/1.1.x/api/org/springframework/web/util/CookieGenerator.html
이곳을 참조..





[mybatis] 반복되는 query 줄이기(sql - include) iBatis/MyBatis

같은 쿼리를 다른 쿼리에서 일부분 사용한다거나  그렇게 반복이 될 때

다음과 같이 사용하면 좋다


...
<mapper>
....


<sql id="a">
SELECT * FROM TABLE1
</sql>


<select id="getList" resultType="hashmap">
<include refid="a" />
WHRE name = #{value}
</select>

</mapper>



1 2 3 4 5 6 7 8 9 10