반응형

MyBatis 어노테이션을 사용하여 SQL을 정의하는 방법이 제공된다.

그러나 문자열 연결에서 SQL을 조립하고 쉼표 구분이라든지 AND, OR 구분 등 주의해야 하는 세세한 것들이 여러 가지가 있다.

그 부분에 대해 귀찮은 부분을 감추는 API를 제공하고 있다.

소스 코드

sample_mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="sample.mybatis.TestTableMapper"> <!-- Mapper을 namespace에 지정 -->
</mapper>

TestTableMapper.java

package sample.mybatis;

import java.util.List;

import org.apache.ibatis.annotations.SelectProvider;

// Mapper 인터페이스로 만든다
public interface TestTableMapper {
    // @SelectProvider으로 SQL을 생성하는 클래스 메소드를 설정한다
    @SelectProvider(type=TestTableSqlProvider.class, method="getSelectTestSql")
    List<TestTable> selectTest();
}

TestTableSqlProvider.java

package sample.mybatis;

import org.apache.ibatis.jdbc.SQL;

// SQL을 생성하는 클래스
public class TestTableSqlProvider {

    // SQL을 생성하는 메소드
    public String getSelectTestSql() {
        // SQL 클래스를 사용하여 SQL을 생성한다.
        SQL sql = new SQL() {{ // 익명의 클래스 생성
            SELECT("id, hoge_value");
            SELECT("fuga_value");
            SELECT("piyo_value");
            FROM("test_table");
        }};

        return sql.toString();
    }
}

Main.java

package sample.mybatis;

import java.io.InputStream;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class Main {

    public static void main(String[] args) throws Exception {
        try (InputStream in = Main.class.getResourceAsStream("/mybatis-config.xml")) {
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);

            try (SqlSession session = factory.openSession()) {
                TestTableMapper mapper = session.getMapper(TestTableMapper.class);
                mapper.selectTest();
            }
        }
    }
}

실행 결과

[DEBUG] s.m.T.selectTest - ==>  Preparing: SELECT id, hoge_value, fuga_value, piyo_value FROM test_table WHERE (hoge_value is not null) 
[DEBUG] s.m.T.selectTest - ==> Parameters: 

설명

  • Mapper의 메소드를 @SelectProvider에서 어노테이션을 지정한다.
    • type에 SQL을 생성하는 클래스로 하고, method에 SQL을 생성하는 메소드의 이름을 지정한다.
    • INSERT 또는 UPDATE에는 @InsertProvider과 @UpdateProvider가 있다.
  • SQL 생성에는 org.apache.ibatis.jdbc.SQL 클래스를 사용한다.
  • SQL 클래스를 익명 클래스로 new하여 인스턴스 초기화 블록에서 SELECT()와 FROM() 메소드를 사용하여 SQL을 생성한다.
    • 각 인수는 문자열에서 SQL의 항목을 전달한다.
    • 이때 쉼표 구분 등은 필요에 따라 추가되기도 한다.
  • 생성된 SQL 인스턴스의 toString() 메소드에서 생성한 SQL을 문자열로 검색할 수 있다.



각 메소드의 사용법에 대해

SELECT

new SQL() {{
    SELECT("foo");
    SELECT("bar");
    SELECT("fizz, buzz");
    FROM("foo_table");
}};
SELECT foo, bar, fizz, buzz FROM foo_table 
  • 연속하여 작성하면, 각 항목을 쉼표로 마음대로 구분된다.
  • 명시적으로 쉼표로 구분된 문자열 전달도 된다.
  • 끝에 불필요한 쉼표가 있는 경우, 제거해 주지 않는다.

FROM

new SQL() {{
    SELECT("*");
    FROM("foo_table");
    FROM("bar_table");
}};
SELECT * FROM foo_table, bar_table 
  • FROM을 연속하여 작성할 경우, 쉼표 구분으로 FROM 절이 열거된다.

WHERE

new SQL() {{
    SELECT("*");
    FROM("foo_table");
    WHERE("foo = ?");
    WHERE("bar = ?");
    AND();
    WHERE("fizz = ?");
    WHERE("buzz = ?");
    OR();
    WHERE("hoge = ?");
    WHERE("fuga = ?");
}};
SELECT *
  FROM foo_table
 WHERE (
       foo = ?
       AND bar = ?
 ) AND (
       fizz = ?
       AND buzz = ?
 )  OR (
       hoge = ?
       AND fuga = ?
 ) 
  • WHERE() 메소드로 WHERE 절을 생성할 수 있다.
  • WHERE() 메소드를 연속하여 작성하면 AND 조건으로 연결된다.
  • AND() 및 OR() 메소드를 사용하면 AND, OR로 연결할 수 있다.

INNER_JOIN

new SQL() {{
    SELECT("*");
    FROM("foo_table");
    INNER_JOIN("bar_table on bar_table.id = foo_table.bar_id");
    INNER_JOIN("fizz_table on fizz_table.id = bar_table.fizz_id");
}};
    SELECT *
      FROM foo_table
INNER JOIN bar_table
        on bar_table.id = foo_table.bar_id
INNER JOIN fizz_table
        on fizz_table.id = bar_table.fizz_id 
  • INNER_JOIN() 메소드으로 INNER JOIN 절을 추가할 수 있다.
  • 조인 조건 문자열( on~)을 작성해야 한다.

ORDER_BY

new SQL() {{
    SELECT("*");
    FROM("foo_table");
    ORDER_BY("foo");
    ORDER_BY("bar desc");
}};
SELECT * FROM foo_table ORDER BY foo, bar desc 
  • ORDER_BY() 메소드로 ORDER BY 절을 생성할 수 있다.
  • 연속하여 작성되면 자동으로 쉼표로 구분된다.

GROUP_BY

new SQL() {{
    SELECT("foo, bar");
    FROM("foo_table");
    GROUP_BY("foo");
    GROUP_BY("bar");
}};
SELECT foo, bar FROM foo_table GROUP BY foo, bar 
  • GROUP_BY() 메소드로 GROUP BY 절을 생성할 수 있다.
  • 연속하여 작성되면 자동으로 쉼표로 구분된다.

HAVING

new SQL() {{
    SELECT("foo, count(*)");
    FROM("foo_table");
    GROUP_BY("foo");
    HAVING("0 < count(*)");
    HAVING("count(*) < 100");
}};
  SELECT foo
        ,count(*)
    FROM foo_table
GROUP BY foo
  HAVING (
         0 < count(foo)
         AND count(foo) < 100
  )
  • HAVING() 메소드로 HAVING 절을 생성할 수 있다.
  • WHERE()와 같은 동작을 한다 (연속하여 작성하면 AND로 연결된다).

INSERT_INTO, VALUES

new SQL() {{
    INSERT_INTO("foo_table");
    VALUES("foo_value", "#{foo_value}");
    VALUES("fizz_value, buzz_value", "#{fizz_value}, #{buzz_value}");
}};
INSERT INTO foo_table (foo_value, fizz_value, buzz_value) VALUES (?, ?, ?) 
  • INSERT_INTO() 메소드로 INSERT 문을 생성할 수 있다.
  • VALUES() 메소드로 등록할 항목을 정의할 수 있다.
    • 첫 번째 인수에는 설정하는 항목의 이름을 작성하고
    • 두 번째 인수에는 VALUES 절에서 지정한 값을 전달한다.
    • 여러 설명하면 자동으로 쉼표로 구분된다.

UPDATE, SET

new SQL() {{
    UPDATE("foo_table");
    SET("foo_value = #{foo_value}");
    SET("bar_value = #{bar_value}");
    WHERE("id = #{id}");
}};
UPDATE foo_table SET foo_value = ?, bar_value = ? WHERE (id = ?)
  • UPDATE() 메소드에서 UPDATE 문을 생성할 수 있다.
  • SET() 메소드에서 SET 절을 생성할 수 있다.
  • 연속하여 작성되면 자동으로 쉼표로 구분된다.

DELETE_FROM

new SQL() {{
    DELETE_FROM("foo_table");
    WHERE("id = #{id}");
}};
DELETE FROM foo_table WHERE (id = ?) 
  • DELETE_FROM() 메소드로 DELETE 문을 생성할 수 있다.



반응형

'MyBatis' 카테고리의 다른 글

[MyBatis] Spring Boot와 연계  (0) 2017.12.31
[MyBatis] 프로그램에서 SQL을 동적으로 생성  (0) 2017.12.31
[MyBatis] 동적 SQL  (0) 2017.12.31
[MyBatis] Mapper  (0) 2017.12.31
[MyBatis] 배치(batch) 갱신  (0) 2017.12.31
[MyBatis] 삭제 DELETE  (0) 2017.12.31

+ Recent posts