MyBatis 연동
① pom.xml
- <dependency> 추가
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
spring-jdbc, spring-tx : 스프링에서 데이터베이스와 트랙잭션 처리와 관련
(MyBatis와 무관해 보여도 추가하지 않으면 에러 발생)
mybatis, mybatis-spring : MyBatis와 스프링 연동용 라이브러리
② root-context.xml
- <bean> 추가
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
</bean>
MyBatis에서 가장 핵심적인 객체들
- SQLSessionFactory : SQLSession을 내부적으로 생성
- SQLSession : 얘를 통해 Connection 생성하거나 원하는 SQL 전달하고 결과를 리턴받는 구조로 작성
코드의 패키지명을 보면 MyBatis의 패키지가 아니라 mybatis-spring(스프링과 연동 작업 처리) 라이브러리의 클래스임
③ src/main/java/(__.__.mapper 패키지).TimeMapper.java
package com.spring.mapper;
import org.apache.ibatis.annotations.Select;
public interface TimeMapper {
@Select("SELECT sysdate FROM dual")
public String getTime();
public String getTime2();
}
Mapper를 통해 SQL을 어떻게 처리할지 설정을 분리하고, 자동으로 처리하는 방식을 이용할 것.
Mapper는 SQL과 그에 대한 처리를 지정하는 역할을 하는데, MyBatis-Spring 이용 시 Mapper를 XML과 인터페이스 + 어노테이션 형태로 작성 가능
- getTime() : XML 사용하지 않는 방법. @SELECT는 MyBatis 어노테이션이다. 편리하다는 장점
- getTime2() : XML 사용하는 방법. SQL이 길고 복잡해질 경우 더 선호됨
④ root-context.xml
- Namespaces - mybatis-spring 체크
- base-package 추가
<mybatis-spring:scan base-package="com.spring.mapper"></mybatis-spring:scan>
여기서 지정된 패키지의 모든 MyBaits 관련 어노테이션을 찾아 처리함
각각 XML이나 Mapper 인터페이스 설정할 수도 있지만, 매번 하기에 번잡해서 자동으로 com.spring.mapper 패키지를 인식하는 방법을 사용한 것
⑤ src/main/resources/(__.__.mapper 패키지).TimeMapper.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="com.spring.mapper.TimeMapper">
<select id="getTime2" resultType="string">
SELECT sysdate FROM dual
</select>
</mapper>
아래는 위 코드에 대한 설명
<mapper namespace="com.spring.mapper.TimeMapper">
Mapper 사용 시 위 내용을 주의해야 함
MyBaits는 Mapper 인터페이스와 XML을 인터페이스 이름과 namespace 속성값으로 판단하기 때문.
com.spring.mapper.TimeMapper 인터페이스 존재하면서 XML의 namespace의 이름이 동일하면 병합해서 처리
(메서드 선언은 인터페이스에 존재하지만 SQL에 대한 처리는 XML을 이용하는 방식)
<select id="getTime2" resultType="string">
SELECT sysdate FROM dual
</select>
위에서 볼 수 있듯, id 속성값은 메서드 이름과 동일해야 하고 resultType 속성값(<select>의 경우)은 인터페이스에 선언된 메서드 리턴 타입과 동일해야 함
테스트 코드
① src/test/java/(__.__.persistence 패키지).TimeMapperTests.java
package com.spring.persistence;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.spring.mapper.TimeMapper;
import lombok.Setter;
import lombok.extern.log4j.Log4j;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class TimeMapperTests {
@Setter(onMethod_ = @Autowired)
private TimeMapper timeMapper;
@Test
public void testGetTime() {
log.info(timeMapper.getClass().getName());
log.info(timeMapper.getTime());
}
@Test
public void testGetTime2() {
log.info("getTime2");
log.info(timeMapper.getTime2());
}
}
위 코드 정상 동작한다면 스프링 내부에 TimeMapper 타입으로 만들어진 스프링 객체(빈)가 존재한다는 뜻.
timeMapper.getClass().getName()은 실제 동작하는 클래스 이름을 확인해줌
log4jdbc-log4j2 라이브러리 설정
MyBatis는 내부적으로 JDBC의 PreparedStatement 이용해 SQL을 처리하므로 SQL에 전달되는 파라미터가 JDBC에서처럼 '?'로 치환되어 처리된다.
'?'로 나오는 값이 제대로 되었는지 실행된 SQL 내용을 정확히 확인할 수 있도록 SQL을 변환하여 '?'가 어떤 값으로 처리되었는지 확인하기 위해. 즉, SQL 로그를 제대로 보기 위해 사용함
① pom.xml
- <dependency> 추가
<!-- https://mvnrepository.com/artifact/org.bgee.log4jdbc-log4j2/log4jdbc-log4j2-jdbc4 -->
<dependency>
<groupId>org.bgee.log4jdbc-log4j2</groupId>
<artifactId>log4jdbc-log4j2-jdbc4</artifactId>
<version>1.16</version>
</dependency>
② src/main/resources/log4jdbc.log4j2.properties
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
③ root-context.xml
- <bean> hikariConfig <property> driverClassName, jdbcUrl value 수정
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="driverClassName"
value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
<property name="jdbcUrl"
value="jdbc:log4jdbc:oracle:thin:@localhost:1521:orcl"></property>
<property name="username" value="아이디"></property>
<property name="password" value="패스워드"></property>
</bean>
제대로 설정되지 않으면 로그가 정상적으로 기록되지 않는다.
로그 레벨 설정
<logger name="jdbc.audit">
<level value="warn" />
</logger>
<logger name="jdbc.resultset">
<level value="warn" />
</logger>
<logger name="jdbc.connection">
<level value="warn" />
</logger>
테스트 코드 실행될 때의 로그와 관련된 설정을 변경할 수 있음
위 코드를 추가하면 jdbc에 대한 로그 중, 좀 더 높은 레벨의 로그만 기록하게 됨 (기본은 info)
'Spring > Spring Framework Document' 카테고리의 다른 글
[Spring Framework] Overview (1) (0) | 2020.06.14 |
---|---|
시작하기에 앞서 (0) | 2020.06.09 |