본문 바로가기

Spring/Spring Framework Document

[Spring Framework] MyBatis 연동, log4jdbc-log4j2 설정

728x90
반응형

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()은 실제 동작하는 클래스 이름을 확인해줌

testGetTime() 실행 시 생성되는 로그
testGetTime2() 실행 시 생성되는 로그

 

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>

제대로 설정되지 않으면 로그가 정상적으로 기록되지 않는다.

test 코드 다시 실행 시 JDBC 관련 로그도 함께 출력되는 로그

 

로그 레벨 설정

	<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)

테스트 코드 실행 시 로그가 줄어든 것을 확인할 수 있음

 

728x90
반응형

'Spring > Spring Framework Document' 카테고리의 다른 글

[Spring Framework] Overview (1)  (0) 2020.06.14
시작하기에 앞서  (0) 2020.06.09