Tag Archives: 프로그래밍

Spring ActiveRowMapper 사용하기

스프링의 멋진 기능들에 현혹되어있다 보면 딱 한가지 마음에 안드는것이 있다.

JDBCTemplate 클래스의 멋진기능에 흠집이라도 낼려고 작정한것 같다. 바로 SELECT시에 수많은 필드별로 값을 지정하는 RowMapper 클래스를 제작해야 한다.

이곳 저곳 구글링을 해봤지만, 달리 방법은 없는듯 하다. 하지만 무언가 풀려서는 안되는 괴물 탈옥수 처럼 스프링의 샌드박스에 잠들어있는 녀석이 있었다.

그 이름하여 바로 ActiveRowMapper !이녀석은 삽질한 소스코드를 한 한줄로 줄여버린다.

기존의 소스코드 :
[code]String query = “SELECT EMP_NAME, EMP_GRADE, EMP_DEPT, EMP_PHONE FROM EMPLOYEE”;

ParameterizedRowMapper<Employee> rowMapper = new ParameterizedRowMapper<Employee>() {

 public User mapRow(ResultSet rs, int rowNum) throws SQLException
 {
  Employee empoyee = new Employee();
   
  empoyee .setEmpName(rs.getString(“EMP_NAME”));
  empoyee .setEmpGrade(rs.getString(“EMP_GRADE”));
  empoyee .setEmpDept(rs.getString(“EMP_DEPT”));
  empoyee .setEmpPhone(rs.getString(“EMP_PHONE”));
   
  return empoyee;
 }
};
 
Employee empoyee = jdbcTemplate.queryForObject(query, rowMapper);[/code]

새로운 소스코드 :
[code]String query = “SELECT EMP_NAME, EMP_GRADE, EMP_DEPT, EMP_PHONE FROM EMPLOYEE”;

ActiveRowMapper rowMapper = new ActiveRowMapper(Employee.class);

Employee empoyee = jdbcTemplate.queryForObject(query, rowMapper);[/code]

어떤가? 매우 산뜻하게 바뀌었다. 하지만 이녀석이 정식 마엘스톰에 못올라가고 있는 이유가 있는듯 하다.

다이나믹 하지 못하다. 나름 문제점이 있는거 같다. 우선 하나 꼬집어 보자면, 관례상 DB의 필드명은 언더바가 들어가고 Java에서는 낙타등 표기법으로 표기한다.

즉 디비에는 필드명이 “EMP_NAME” 이지만 Java Bean에서는 “empName” 으로 지정해야 한다. 물론 String 형이겠죠.

Java 표준 규약에 따르면 “empName” 이라는 변수에 값을 세팅 하는 셋터의 이름은 “setEmpName”이다.

고로 ActiveRowMapper는 입력해야할 셋터를 찾아가기 위해 다음과 과정을 거친다.

1. 필드명 소문자화 : EMP_NAME → emp_name
2. 언더바를 기준으로 토큰화 : emp_name → [1] emp, [2] name
3. 나누어진 열을 병합(첫글자는 대문자로 변환) : [1] emp, [2] name → EmpName
4. 앞에 set을 붙임 : EmpName → setEmpName

고로 이것을 명심해야만 에러없는 ActiveRowMapper를 사용할수 있다.

디비 EMP_NAME == 자바 empName

끝으로 샌드박스에서 잠자고 있던 1.4 소스를 올린다.
1248502711.java

Lucene 인덱싱 옵션

블로그에 적어놓겠다고 한지 3달도 더 지난거 같다. 지금 빨리 안적어 두면 정말로 기억속에서 사라질것 같아 오랜만에 블로그에 글을 적는다.

루씬 2.0부터 바뀐 인덱싱 옵션 지정방법에 대해 정리하겠다.

보통의 인덱싱은 Document 클래스를 이용하여 다음과 같이 지정한다.

[code]Document document = new Document();
document.add(new Field(“area”, area, Store.YES, Index.UN_TOKENIZED));
document.add(new Field(“vmag”, vmag, Store.YES, Index.UN_TOKENIZED));
document.add(new Field(“count”, count, Store.YES, Index.NO));
document.add(new Field(“data”, data, Store.YES, Index.NO));
writer.addDocument(document);[/code]

정확히는 Field 객체를 넣는것이다.

Field 의 인자값은 다음과 같다.

[code]Field(필드명, 변수명, 저장옵션, 인덱스옵션)[/code]

첫번째 필드명은 데이터페이스의 필드를 생각하면 되겠다. 어떤 이름의 필드에 저장할것인지를 정한다.

두번째 변수명에는 위에서 지정한 해당 필드명에 들어갈 값을 지정해 주면 된다.

세번째 저장옵션에는 해당 전체 값을 인덱스에 저장할것인지를 정한다. 다음과 같은 옵션이 있다.



  • Store.YES : 인덱스를 할 값 모두를 인덱스에 저장한다. 검색결과등에서 꼭 보여야 하는 내용이라면 사용한다.
  • Store.NO : 값을 저장하지 않는다. Index 옵션과 혼합하여, 검색은 되데, 원본글이 필요없을 경우 사용될수 있다.
  • Store.COMPRESS : 값을 압축하여 저장한다. 저장할 글의 내용이 크거나, 2진 바이너리 파일등에 사용한다.


네번째 인덱스 옵션에는 검색을 위한 인덱스 생성 방식을 정한다.



  • Index.NO : 인덱싱을 하지 않는다. 고로 이렇게 저장한 값으로 검색을 할수 없다.
  • Index.TOKENIZED : Analyzer에 의한 토크나이즈를 수행하여 인덱싱을 한다. 물론 검색 가능하다.
  • Index.UN_TOKENIZED : 토크나이즈를 수행하지 않는다. 숫자라거나, 쪼갤필요가 없는 문자열에 사용하면 된다. 물론 검색이 되며, Analyze를 수행하지 않기때문에 인덱스 속도가 빠르다.
  • Index.NO_NORMS : 이것은 인덱싱 시간이 매우 빨라야 할때 사용한다. Analyze를 수행하지 않는다. 또한 필드 Length 노멀라이즈를 수행하지 않는다. 인덱싱시에 적은 메모리만을 사용하게 된다는 장점이 있다.

다음으로 예를 들어 사용법을 숙지하도록 하여보자.

1. 저장할 내용은 수필형식의 글이다. 해당 필드로 검색이 되어야 하며, 검색결과에서 바로 해당 글의 전문이 출력되어야 한다.
=> Store.YES, Index.TOKENIZED

2. 저장할 내용은 20070606 같은 형식을 가지는 띄어쓰기가 없는 날짜이다. 해당 필드로 검색이 되어야 하며, 검색어와 검색결과가 동일할테니 글의 내용을 저장할 필요는 없다.
=> Store.NO Index.Index.UN_TOKENIZED

3. 저장할 내용은 영화 제목과 영화 사용기이다. 영화 제목만으로 검색을 할수 있으며, 사용기의 전문으로 검색은 되지 않는다. 하지만 검색결과에서 사용기가 출력되어야 한다.
=> 제목 Field : Store.YES, Index.TOKENIZED / 사용기 Field : Store.YES, Index.NO