토비의 스프링 3의 예제 추가 설명의 마지막 글이다. 에이콘 블로그에 토스3 책 소개도 마침 올라왔다. 책만큼이나 긴 소개 글이다. 오늘 이 글로 예제 설명은 마치고 내일부터는 지난 3년 6개월동안 책을 써온 얘기를 한번 적어볼까 한다.

오늘 설명할 내용은 책의 부록CD에 있는 Springusergroup 프로젝트에 사용된 BeanPropertySqlParameterSource의 확장 클래스에 대한 설명이다.

BeanPropertySqlParameterSource는 NamedParameterJdbcTemplate에서 사용되는 파라미터 이름 정보제공 오브젝트의 구현 인터페이스인 SqlParameterSource의 구현 클래스이다. NamedParameterJdbcTemplate의 기능은 대부분 SimpleJdbcTemplate에서도 제공된다. 따라서 스프링JDBC를 사용한다면 메소드에서 SqlParameterSource 타입 파라미터를 자주 발견할 수 있다.

SqlParameterSource는 JDBC에서 사용하는 위치 치환자(?) 대신 이름 치환자(:이름)을 지원하는 메소드에서 각 이름에 해당하는 값을 제공해주기 위해서 사용된다. 예를 들어 select * from users where name = :name and age = :age 라는 이름 치환자를 가진 SQL을 사용했을 경우 :name과 :age에 넣어줄 값을 담은 오브젝트를 전달해야 하는데, 이 때 사용하는 오브젝트의 타입이 바로 SqlParameterSource라는 것이다. SqlParameterSource을 구현한 클래스는 대표적으로 MapSqlParameterSource와 BeanPropertySqlParameterSource을 들 수 있다. 전자는 맵에 직접 이름과 값 쌍을 넣어주는 것이고 후자는 자바빈 스타일의 오브젝트에 값을 넣어서 전달하는 것이다. 개발자의 선호도에 따라서 다르겠지만, 일반적으로는 보통 후자의 빈 프로퍼티를 이용한 방식이 더 자주 사용된다. 단순한 조건용 파라미터가 아니라 INSERT나 UPDATE 같은 테이블 값을 통채로 넣는 경우에는 아예 도메인 오브젝트나 DTO에 값을 넣어서 전달하는 것이 편리하기 때문이다.

BeanPropertySqlParameterSource 사용은 INSERT 문을 자동 생성해주는 SimpleJdbcInsert에서 가장 빛을 발한다. SimpleJdbcInserth는 INSERT INTO USERS VALUES(:id, :name ….) 과 같이 일일이 INSERT 문을 작성하지 않아도 DB에서 테이블-필드 메타 정보를 읽어와서 이를 이용해서 자동으로 SQL로 만들어 준다. 여기에 BeanPropertySqlParameterSource 를 결합하면 테이블 필드 이름과 오브젝트 프로퍼티를 일치시켜주는 것만으로 DB 등록 작업이 매우 수월하게 처리된다. 명시적인 설정정보 없이 적절한 관례와 명명규칙, 그리고 메타 정보를 활용하는 방식이다. 예를 들어 User 테이블에 id, name, age 라는 필드가 있다면, 그에 대응 되는 id, name, age 프로퍼티를 User 클래스의 오브젝트를 이용해서 SQL 작성 없이 간단히 INSERT 작업을 할 수 있다.

DB에서 읽은 메타 정보, 즉 필드 이름을 이용해서 파라미터로 전달된 오브젝트에서 값을 읽어올 때 사용되는 것이 바로 BeanPropertySqlParameterSource 이다.

문제는 이름이 일치하지 않는 경우이다. 단순히 name->nm 식으로 다른 것은 별 문제가 되지 않는다. 문제는 아예 오브젝트에서 정보를 가져오는 단위나 방법이 다른 경우이다. Springusergroup의 예를 들자면 User 클래스의 다음 두 개 프로퍼티가 문제가 된다.

class User {
    Group group;
    Type type;
    …

Group는 다른 엔티티, 즉 다른 오브젝트를 가리키는 레퍼런스 변수다. 자바 오브젝트로 DB의 테이블 관계를 나타낼 때는 FK 값(Group이라면 group_id)이 아니라 해당 오브젝트를 통채로 지정해야 한다. 따라서 테이블의 메타 정보에는 group_id라는 이름의 FK 필드 이름이 나오지만 이를 오브젝트 관계에서는 getGroup().getId()처럼 해당하는 값을 레퍼런스를 타고 관련 오브젝트에 가서 읽어와야 한다. EL로 표현하자면 group.id다. 메타정보와 실제 프로퍼티가 일치하지 않는다.

Type은 그 자체로 독립적인 테이블에 매핑되는 엔티티는 아니다. 여기서 Type은 enum이다. Enum도 오브젝트이므로 바로 매핑을 할 수 없다. DB메타정보에는 type은 숫자형으로 되어있다. 하지만 BeanPropertySqlParameterSource을 통해서 해당 프로퍼티(type)의 타입을 살펴보면 Type이라는 이해할 수 없는 타입이 나온다. 따라서 이 경우도 기본 관례를 이용한 자동 매핑이 불가능하다. DB테이블의 type에 해당하는 값을 가져오려면 User 오브젝트의 type.value를 가져와야 한다. Type enum에 getValue()를 만들어서 DB에 저장될 숫자값을 가져오도록 만들어뒀기 때문이다. 결국 type –> type.value라는 매핑이 필요하다.

이 두 가지 매핑은 BeanPropertySqlParameterSource 가 기본적으로 제공해주는 단순한 이름 비교로는 불가능하다. 추가적인 매핑 정보가 필요하다. 물론 MapSqlParameterSource을 이용해서 모든 파라미터 정보를 키-값 쌍으로 넣어주면 세밀하게 지정이 가능하겠지만, 필드이름과 프로퍼티 이름의 자동 매핑이 가능한 나머지 필드도 일일이 지정해야 하는 번거로움이 있다.

그래서 Springusergroup에는 기본적으로 BeanPropertySqlParameterSource처럼 동작하지만 일부 항목만 필드-프로퍼티 매핑을 지정해줄 수 있도록 확장한 MappedBeanPropertySqlParameterSource을 사용한다. BeanPropertySqlParameterSource는 그다지 확장하기 좋게 만들어진 클래스는 아니지만 SqlParameterSource를 직접 구현하는 것보다는 훨씬 편하므로 BeanPropertySqlParameterSource를 상속해서 만들었다.

사용방법은 간단하다. 다음과 같이 프로퍼티를 제공할 오브젝트를 생성자에 전달하고 추가 매핑이 필요한 필드-프로퍼티 정보를 map() 메소드로 지정해주면 된다.

new MappedBeanPropertySqlParameterSource(user)
                    .map("type","type.value").map("group_id", "group.id");

일반 필드에 대해서는 DB테이블의 이름과 User오브젝트의 프로퍼티 이름을 바로 매핑해서 정보를 읽어오고, map()으로 지정한 필드에 대해서는 별도로 지정한 type.value나 group.id을 이용해서 프로퍼티를 가져온다. 이렇게 만든 오브젝트를 미리 준비한 SimpleJdbcInsert 오브젝트의 execute() 메소드에 넣어주기만 하면 INSERT 문이 자동으로 생성되면서 등록 작업이 수행된다.

this.userInsert.execute(new UserBeanPropertySqlParameterSource(user));

여기서는 미리 만들어둔 UserBeanPropertySqlParameterSource를 사용했는데, 등록 뿐 아니라 수정에서도 사용할 수 있기 때문이다. 미리 클래스를 만들어두려면 다음과 같이 생성자에서 초기화 시켜주면 된다.

private static class UserBeanPropertySqlParameterSource extends MappedBeanPropertySqlParameterSource {
    public UserBeanPropertySqlParameterSource(Object object) {
        super(object);
        map("type", "type.value");
        map("groupid", "group.id");
    }
}

Private 스태틱 클래스를 사용한 이유는 UserDao에서만 사용되는 클래스이기 때문이다.

자세한 사용방법과 구현 방식은 출간이 20일로 미뤄진 토비의 스프링 3 예제를 참고하기를. 원래 오늘인 출간이 인쇄사고로 10일 가량 늦어졌다고 하는데 자세한 이유는 잘 모르겠다. 책 한 권 세상에 나오는 것이 이렇게 힘든 일이었구나.

Related posts:

  1. [토스3] 스프링 JDBC DAO에 lazy-loading 적용하기 (2)
  2. [토스3] 스프링 JDBC DAO에 lazy-loading 기능 적용하기
  3. Spring 3.0 @MVC 메소드에서 자동으로 리턴 모델에 추가되는 것들
  4. [토스3] 스프링 3.0.4 <mvc:default-servlet-handler/>를 이용해서 UrlRewriteFilter없이 깔끔한 URL을 만들기
  5. Spring Expressions(SpEL)를 이용한 Mockito Argument Matcher 만들기
  6. AppFuse DAO Test 코드의 문제점
  7. 스크린캐스트 – 테스트와 스프링
  8. 토비의 스프링 3 출간지연과 동영상 소식
  9. 토비의 스프링 3이 나오기까지 (8)
  10. Dependency Injection의 Dependency란 무엇인가?
  11. 토비의 스프링 3이 나오기까지 (3)
  12. 토비의 스프링 3이 나오기까지 (7)
  13. 토비의 스프링 3이 나오기까지 (9)
  14. 토비의 스프링 3이 나오기까지 (11)
  15. 토비의 스프링 3이 나오기까지 (2)

Facebook comments:

to “[토스3] 매핑 가능한 BeanPropertySqlParameterSource”

  1. Greetings! Very helpful advice within this post! It’s the little changes that will make the most significant changes. Thanks a lot for sharing!

  2. Greetings! Very helpful advice in this particular post! It is the little changes that will make the largest changes. Thanks a lot for sharing!

  3. Good day! I just would like to give you a huge thumbs up for the excellent information you have right here on this post. I will be returning to your website for more soon.

  4. Way cool! Some extremely valid points! I appreciate you writing this write-up plus the rest of the site is also really good.

  5. After looking over a number of the articles on your web page, I honestly appreciate your way of blogging. I saved it to my bookmark site list and will be checking back soon. Please check out my website as well and let me know how you feel.

  6. This site was… how do I say it? Relevant!! Finally I’ve found something that helped me. Cheers!

  7. Everything is very open with a really clear explanation of the issues. It was really informative. Your site is very helpful. Thanks for sharing!

  8. I’m pretty pleased to discover this website. I wanted to thank you for ones time due to this fantastic read!! I definitely loved every part of it and I have you saved as a favorite to look at new stuff in your website.

  9. Having read this I believed it was rather enlightening. I appreciate you taking the time and energy to put this informative article together. I once again find myself spending a lot of time both reading and posting comments. But so what, it was still worthwhile!

  10. Aw, this was an exceptionally good post. Taking the time and actual effort to make a top notch article… but what can I say… I put things off a lot and don’t seem to get anything done.

  11. Wonderful post! We are linking to this great article on our site. Keep up the great writing.

  12. Hello there, I do think your blog might be having web browser compatibility problems. Whenever I look at your blog in Safari, it looks fine however when opening in IE, it has some overlapping issues. I simply wanted to provide you with a quick heads up! Apart from that, wonderful blog!

  13. Hi! I could have sworn I’ve visited this site before but after looking at some of the articles I realized it’s new to me. Nonetheless, I’m definitely pleased I discovered it and I’ll be book-marking it and checking back regularly!

  14. This is a topic that’s near to my heart… Best wishes! Exactly where are your contact details though?

  15. Pretty! This was an extremely wonderful article. Many thanks for providing this information.

  16. Good post. I learn something totally new and challenging on websites I stumbleupon on a daily basis. It will always be helpful to read through articles from other writers and practice something from other web sites.

  17. Hi, I do believe this is a great website. I stumbledupon it ;) I may return yet again since i have book marked it. Money and freedom is the best way to change, may you be rich and continue to guide others.

  18. Spot on with this write-up, I really feel this web site needs a lot more attention. I’ll probably be returning to see more, thanks for the info!

  19. Can I just say what a comfort to uncover someone who really knows what they’re talking about on the web. You definitely realize how to bring an issue to light and make it important. More and more people should look at this and understand this side of your story. I was surprised you are not more popular because you certainly have the gift.

  20. You need to be a part of a contest for one of the best sites on the internet. I most certainly will highly recommend this blog!

  21. After looking over a number of the articles on your web site, I seriously appreciate your way of blogging. I added it to my bookmark webpage list and will be checking back in the near future. Please check out my web site as well and tell me how you feel.

  22. I’m impressed, I have to admit. Rarely do I come across a blog that’s equally educative and entertaining, and without a doubt, you’ve hit the nail on the head. The issue is something which too few people are speaking intelligently about. I am very happy I stumbled across this during my hunt for something relating to this.

  23. This is a topic that is near to my heart… Cheers! Exactly where are your contact details though?

  24. Great post! We will be linking to this particularly great post on our website. Keep up the good writing.

  25. Aw, this was a really nice post. Finding the time and actual effort to generate a great article… but what can I say… I put things off a whole lot and never seem to get nearly anything done.

Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2017 Toby's Epril Suffusion theme by Sayontan Sinha