본문 바로가기

3.구현/Java or Kotlin

[ibatis] 리스트형 데이터 사용해서 쿼리 작성하기(iterate)

다음은 여러 값들에 대한 가변적인 쿼리를 생성하기 위한 내용이다. 즉, 일련의 데이터를 반복적으로 순회하면서 한방에 쿼리를 작성하기 위한 부분이다.

작성자: http://ospace.tistory.com/,2016.11.10 (ospace114@empal.com)

기본 환경

예제 환경은 다음과 같다. 이미 iBatis등은 설치되어 있고, 기본적인 구성은 되어 있다고 가정한다. 만약 iBatis에 대한 기본적인 사용법은 다음을 참고하기 바란다

http://aid.altibase.com/pages/viewpage.action?pageId=7340061

다음에 오는 쿼리는 MySQL를 기준으로 작성되었다.

DB 스키마

Table Schema

CREATE TABLE Car (
    car_id   NUMBER(2) NOT NULL,
    car_name VARCHAR2(10) NOT NULL,
    car_style  NUMBER(22) NOT NULL
);

DTO 클래스

Car용 DTO 클래스

class Car {
    private String car_id;
    private String car_name;
    private String car_style;

    public void setCar_id(String car_id) {
        this.car_id = car_id;
    }
    public String getCar_id() {
        return car_id;
    }
    public void setCar_name(String car_name) {
        this.car_name = car_name;
    }
    public String getCar_name() {
        return car_name;
    }
    public void setCar_style(String car_style) {
        this.car_style = car_style;
    }
    public String getCar_style() {
        return car_style;
    }
}

SqlMapClient

기존 쿼리가 있는 파일이 sqlmap_example.xml이라고 하면 SqlMapClient 초기화는 다음과 같다.

//초기화
Reader reader = Resources.getResourceAsRead("sqlmap_example.xml");
SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);

간단한 리스트형

이 경우는 입력되는 값이 리스트형 구조로 iBatis의 iterator 태그를 사용하는 간단한 방법을 살펴보겠다. 먼저 여러 style를 사용해서 여러 자동차 정보를 추가하는 예제를 보자.

입력되는 값이 리스트 형이라고 하면 다음과 같이 처리될 것이다.

List<Car> cars = new ArrayList<>();

Car car1 = new Car();
//car1 초기화
cars.add(car1)
//반복 추가 작업

sqlMap.insert("insertCar", cars);

insertCar라는 SQL 쿼리를 다음과 같이 만들 수 있다.

<insert id="insertCar" parameterClass="java.util.List">
INSERT INTO Car (
    car_id,
    car_name,
    car_style
) VALUES
    <iterate conjunction=",">
        (
            #[].car_id#,
            #[].car_name#,
            #[].car_style#
        )
    </iterate>
</insert>

<iterate>를 이용해서 리스트의 반복 작업을 순서대로 처리할 수 있다. "[]" 표시는 각 반복에서 객체 하나를 의미한다. conjunction 속성은 하나의 반복의 끝나고 다음 순번으로 가기 전에 중간에 붙여지는 문자열이다. 이런 비슷한 속성으로 prepand는 맨 앞에 앞에 한번 붙여지는 문자열이다. 그리고 open와 close는 각 반복 앞과 뒤에 붙여지는 문자열이다. 즉, 앞의 SQL 쿼리를 다음과 같이 변경할 수 있다.

<insert id="insertCar" parameterClass="java.util.List">
INSERT INTO Car (
    car_id,
    car_name,
    car_style
) 
    <iterate prepend="VALUES" open="(" close=")" conjunction=",">
        #[].car_id#,
        #[].car_name#,
        #[].car_style#
    </iterate>
</insert>

사용은 개인의 선택 문제이지만, 가급적이면 하나로 통일해서 작성하는 것이 편하다. 개인적으로 전자를 선호하는데 이는 좀더 쿼리다워 보이기 때문에 좀더 직관적이다. 후자는 쿼리보다 내용에 집중하는데 도움된다.

리스트 포함형

다음은 리스트가 내부에 포함된 경우이다. 즉, DTO 객체 내에 리스트형이 있는 경우이다. 다음과 같은 DTO 클래스인 경우가 될 것이다.

class CarQuery {
    private String car_name;
    private List<String> car_styles;
    public String getCar_name() {
        return car_name;
    }
    public void setCar_name(String car_name) {
        this.car_name = car_name;
    }
    public List<String> getCar_styles() {
        return car_styles;
    }
    public void setCar_styles(List<String> car_styles) {
        this.car_styles = car_styles;
    }
}

데이터 조회를 코드를 다음과 같이 작성한다고 하면,

List<String> styles = new ArrayList<>();
styles.add("styleA");
//중략
CarQuery carQuery = new CarQuery();  
carQuery.setCar_name("Small");
carQuery.setCar_styles(styles);
List<User> uses = (List<User>) sqlMap.queryForList("selectCar", carQuery);

selectCar에 대한 쿼리를 작성해보자.

<select id="selectCar" parameterClass="com.ospace.example.CarQuery" resultClass="com.ospace.example.Car">
SELECT *
FROM Car
WHERE car_name = #car_name#
  AND car_style IN (
    <iterate property="car_styles" conjunction=",">
        #car_styles[]#
    </iterate>
  )
</select>

<iterate>의 속성인 property를 사용했다. 이를 이용해서 인자로 넘어온 CarQuery의 필드인 car_styles를 접근할 수 있게된다. 다음에 "[]" 앞에 해당 필드명을 명시하면 된다. 현재는 String 값을 직접 접근하고 있지만, 만약에 다른 클래스로 되어 있다면 앞애서 사용했던 마침표(".")를 사용해서 접근하면 된다. (ex. #cars[].car_name#)

결론

아파치에서는 iBatis는 현재 더이상 개발되고 있지 않다. 현재 구글로 옮겨서 myBatis로 진행되고 있다. 그렇다고 모든 것이 똑같지 않다. 앞의 <iterate>는 <foreach>로 변경되었다. 그래도 아직까지 iBatis를 사용하고 있어서 일부러 글을 작성했다.
참고로 앞의 예제는 List를 사용했지만, Map도 동일하게 적용된다. Map도 단순하게 순서대로 조회하는 것이기 때문에 나머지 문법은 동일하다.

참조

[1] Dynamic SQL, ibatis.apache.org, https://ibatis.apache.org/docs/dotnet/datamapper/ch03s09.html

반응형

'3.구현 > Java or Kotlin' 카테고리의 다른 글

[Java] RTP 서버 간단히 구현하기  (0) 2021.01.12
[java] enum 사용하기  (0) 2016.11.11
JSP 간단하게 시작하기...  (0) 2008.12.05
Java 쓰레드 간단한 코드 예제  (0) 2008.07.24
Java 쓰레드 상태  (0) 2008.07.24