반응형
테스트 실행 시간을 단축하기 위해 인메모리 DB인 H2 DB를 종종 사용한다. JDBC URL에서 MODE 프로퍼티를 지정하면 MySQL, 오라클 용 쿼리를 사용할 수 있어 편리한 점도 있다. 예를 들어 다음과 같이 MODE 값으로 MySQL을 주면 H2 DB를 사용하면서 MySQL의 limit을 사용할 수 있다.
jdbc:h2:mem:progress;DATABASE_TO_UPPER=false;MODE=MySQL;DB_CLOSE_DELAY=-1
MODE를 사용해도 특정 DB에 특화된 기능을 사용할 수 없을 때가 발생한다. 예를 들면 MySQL의 inet_aton() 함수나 inet_ntoa() 함수는 H2 DB에서는 사용할 수 없다. 통합 테스트 코드를 실행할 때 H2 DB에서 지원하지 않는 함수를 쿼리에서 사용하면 에러가 발생하기 때문에 이런 함수를 대체할 수 있는 수단을 찾아야 한다.
다행히 H2는 사용자 정의 함수 기능을 지원해서 이 문제를 어렵지 않게 해결할 수 있다. 사용자 정의 함수 기능을 사용하려면 다음 두 가지 작업만 하면 된다.
- 사용자 정의 함수에서 호출할 정적 메서드 구현
- create alias를 이용한 커스텀 함수 생성
먼저 커스텀 함수에서 호출할 정적 메서드를 구현한다.
package util;
public class H2CustomFunc {
public static Long inet_aton(String value) {
if (value == null) return null;
else return ...생략;
}
public static String inet_ntoa(Long value) {
if (value == null) return null;
else return ...생략;
}
}
다음은 인메모리 H2에 테이블을 생성할 때 다음 쿼리를 실행한다.
CREATE ALIAS IF NOT EXISTS inet_ntoa FOR "util.inet_ntoa"
CREATE ALIAS IF NOT EXISTS inet_aton FOR "util.inet_aton"
이제 H2에 연동할 때 inet_ntoa() 함수나 inet_aton() 함수를 사용할 수 있다.
return jdbcTemplate.query("select " +
"uid, content_div, use_yn, " +
"view_start_dt, view_end_dt, " +
"settings, memo, " +
"reg_id, reg_dt, inet_ntoa(reg_ip) as reg_ip, " +
"upd_id, upd_dt, inet_ntoa(upd_ip) as upd_ip " +
"from progress.featured_contents_mgt " +
"order by uid desc limit ?, ?",
JdbcFeaturedContentsRepository::mapRow,
start, limit);
사용자 정의 함수에 대한 내용은 자세한 내용은 아래 문서를 참고한다.
- http://www.h2database.com/html/features.html#user_defined_functions
- https://www.h2database.com/html/commands.html#create_alias