데이터 접근 기술 - MyBatis

존스노우·2023년 11월 21일
0
post-thumbnail

  • mapper 클래스들

  • id 에는 매퍼 인터페이스에 설정한 메서드 이름을 지정하면 된다. 여기서는 메서드 이름이 save() 이므로
    save 로 지정하면 된다

  • 파라미터는 #{} 문법을 사용하면 된다. 그리고 매퍼에서 넘긴 객체의 프로퍼티 이름을 적어주면 된다.

  • #{} 문법을 사용하면 PreparedStatement 를 사용한다. JDBC의 ? 를 치환한다 생각하면 된다.

  • useGeneratedKeys 는 데이터베이스가 키를 생성해 주는 IDENTITY 전략일 때 사용한다. keyProperty 는 생성되는 키의 속성 이름을 지정한다. Insert가 끝나면 item 객체의 id 속성에 생성된 값이 입력된다.

  • Update SQL은 를 사용하면 된다.

  • 여기서는 파라미터가 Long id , ItemUpdateDto updateParam 으로 2개이다. 파라미터가 1개만 있으면 @Param 을 지정하지 않아도 되지만, 파라미터가 2개 이상이면 @Param 으로 이름을 지정해서 파라미터를 구분해야 한다.

  • Select SQL은 select 를 사용하면 된다.
  • resultType 은 반환 타입을 명시하면 된다. 여기서는 결과를 Item 객체에 매핑한다.
  • 앞서 application.properties 에
    속성을 지정한 덕분에 모든 패키지 명을 다 적지는 않아도 된다. 그렇지 않으면 모든 패키지 명을 다 적어야 한다.
  • JdbcTemplate의 BeanPropertyRowMapper 처럼 SELECT SQL의 결과를 편리하게 객체로 바로 변환해준다.
  • mybatis.configuration.map-underscore-to-camel-case=true 속성을 지정한 덕분에 언더스코어를 카멜 표기법으로 자동으로 처리해준다. ( item_name itemName )
    package=hello.itemservice.domain
    mybatis.type-aliases-
  • 자바 코드에서 반환 객체가 하나이면 Item , Optional 과 같이 사용하면 되고, 반환 객체가 하나 이상이면 컬렉션을 사용하면 된다. 주로 List 를 사용한다. 다음을 참고하자.

MyBatis 적용3 - 분석

  • ItemMapper 매퍼 인터페이스의 구현체가 없는데 어떻게 동작한 것일까?

    • 애플리케이션 로딩 시점에 MyBatis 스프링 연동 모듈은 @Mapper 가 붙어있는 인터페이스를 조사한다.

    • 해당 인터페이스가 발견되면 동적 프록시 기술을 사용해서 ItemMapper 인터페이스의 구현체를 만든다.

    • 생성된 구현체를 스프링 빈으로 등록한다.

    • itemMapper class=class com.sun.proxy.$Proxy66
    • 로그에 이런식응로 클래스가 나온다.
    • 매퍼 구현체는 예외 변환까지 처리해준다. MyBatis에서 발생한 예외를 스프링 예외 추상화인 DataAccessException 에 맞게 변환해서 반환해준다. JdbcTemplate이 제공하는 예외 변환 기능을 여기서도 제공한다고 이해하면 된다.
    • 매퍼 구현체를 사용하면 스프링 예외 추상화도 함께 적용된다.
    • 마이바티스 스프링 연동 모듈이 많은 부분을 자동으로 설정해주는데, 데이터베이스 커넥션, 트랜잭션과 관련된 기능도 마이바티스와 함께 연동하고, 동기화해준다.

Mybatis 문법

@Select("select id, item_name, price, quantity from item where id=#{id}")
    Optional<Item> findById(Long id);
  • 동적 SQL이 해결되지 않으므로 간단한 경우에만 사용한다.

    문자열 대체(String Substitution)

    • 때로는 파라미터 바인딩이 아니라 문자 그대로를 처리하고 싶은 경우도 있다. 이때는 ${} 를 사용하면 된다.
 @Select("select * from user where ${column} = #{value}")
  User findByColumn(@Param("column") String column, @Param("value") String
  value);
  • ${} 를 사용하면 SQL 인젝션 공격을 당할 수 있다. 따라서 가급적 사용하면 안된다. 사용하더라도 매우 주의깊게 사용해야 한다.
  • 주의를 요함

    재사용 가능한 SQL 조각

    <sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
    
      <select id="selectUsers" resultType="map">
      select
        <include refid="userColumns"><property name="alias" value="t1"/></include>,
        <include refid="userColumns"><property name="alias" value="t2"/></include>
      from some_table t1
        cross join some_table t2
    </select>

  • 별칭을 사용하지 않고도 문제를 해결할 수 있는데, 다음과 같이 resultMap 을 선언해서 사용하면 된다.

복잡한 결과매핑

  • MyBatis도 매우 복잡한 결과에 객체 연관관계를 고려해서 데이터를 조회하는 것이 가능하다. 이때는 , 등을 사용한다.
  • 이 부분은 성능과 실효성에서 측면에서 많은 고민이 필요하다.
  • JPA는 객체와 관계형 데이터베이스를 ORM 개념으로 매핑하기 때문에 이런 부분이 자연스럽지만, MyBatis에서는 들어가는 공수도 많고, 성능을 최적화하기도 어렵다. 따라서 해당기능을 사용할 때는 신중하게 사용해야 한다.
profile
어제의 나보다 한걸음 더

0개의 댓글