본문으로 바로가기

728x90

본 글에서는 String Boot 프로젝트에 MyBatis 와 log4jdbc-log4j2 를 설정하는 방법에 대하여 정리합니다.

 

 

MyBatis 설정

pom.xml 수정

  • org.mybatis:mybatis, org.mybatis:mybatis-spring을 설정하여 관련 라이브러리를 추가합니다.
  • 데이터베이스 연결 Pool을 위해 com.zaxxer:HikariCP를 추가합니다.(옵션으로 추가하지 않아도 상관없으며 환경설정에서 잃어오는 방법이 약간 다릅니다.) Spring Framework 3.x 이상에서는 자동으로 HikariCP가 기본으로 적용되었습니다.
<dependency>
	<groupId>com.zaxxer</groupId>
	<artifactId>HikariCP</artifactId>
</dependency>
		
<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis</artifactId>
	<version>3.5.0</version>
</dependency>
		
<dependency>
	<groupId>org.mybatis</groupId>
	<artifactId>mybatis-spring</artifactId>
	<version>2.0.0</version>
</dependency>

jdbc 연결정보 수정

여러 개의 데이터베이스 연결을 가능하도록 처리하기 위해 prefix를 추가하였습니다. 일반적인 상황이라면 추가하지 않아도 됩니다.

#spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.oauth.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.oauth.jdbc-url=jdbc:mysql://host:port/dbname?characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.oauth.username=user
spring.datasource.oauth.password=password

mybatis-congif.xml 설정

데이터베이스 컬럼이름의 _에 해당하는 문자열이 있으며 자동으로 대문자처리하도록 mapUnderscoreToCamelCase 옵션을 추가합니다. 예를 들어 데이터베이스 컬럼이 user_name 이라면 연결되는 java의 변수명은 userName와 자동매핑되도록 처리됩니다.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<settings>
		<setting name="mapUnderscoreToCamelCase" value="true" />
	</settings>
</configuration>

DatabaseConfig.java 생성하기

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

@Configuration
@PropertySource("classpath:/application.properties")
public class DatabaseConfig {
	private static final Logger log = LoggerFactory.getLogger(DatabaseConfig.class);
	
	@Bean
	@ConfigurationProperties(prefix = "spring.datasource.oauth")
	public HikariConfig hikariConfig() {
		return new HikariConfig();
	}

	@Bean
	public DataSource dataSource() {
		DataSource dataSource = new HikariDataSource(hikariConfig());
		log.info("datasource : {}", dataSource);
		return dataSource;
	}
	
	@Autowired
	private ApplicationContext applicationContext;

	@Bean
	public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
		SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
		sqlSessionFactoryBean.setDataSource(dataSource);
		sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:/mapper/**/*.xml"));
		
		//Mybatis config파일 위치
		Resource myBatisConfig = new PathMatchingResourcePatternResolver().getResource("classpath:mybatis-config.xml");
		sqlSessionFactoryBean.setConfigLocation(myBatisConfig);
		
		return sqlSessionFactoryBean.getObject();
	}

	@Bean
	public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
		return new SqlSessionTemplate(sqlSessionFactory);
	}
}

mapper 작성

src/main/resources에 mapper 디렉토리리를 생성하고 그 위치에 user_sql.xml 과 같은 파일들을 생성하여 mybatis에서 자동으로 데이터베이스 질의문이 읽혀질 수 있도록 합니다. 파일의 맨 상단의 2줄(<?xml 구문과 <!DOCTYPE 구문)이 없으면 해당 파일을 정상적으로 처리하지 못하니 반드시 추가해야 합니다.

<?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="user">
	<select id="selectUserById" resultType="User">
		<![CDATA[
		SELECT
		    *
		FROM
		    oauth_user_details
		WHERE
		    username = #{username}
		]]>
	</select>
</mapper>

Sample Code 작성

SqlSessionTemplate 객체를 사용하여 mapper에 설정된 데이터베이스 질의문를 수행합니다.

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository("userDAO")
public class UserDAO {
	@Autowired
	private SqlSessionTemplate sqlSession;
	
	public User getUserById(String id) {
		return sqlSession.selectOne("user.selectUserById", id);
	}
}

 

log4jdbc 설정

본 설정은 개발시에 데이터베이스 질의문과 결과를 여러 줄로 나눠서 예쁘게 로그를 출력하기 위한 라이브러리 설정입니다.

pom.xml 수정

로그출력을 위한 라이브러리를 추가합니다.

<!-- MyBatis sql pretty -->
<dependency>
	<groupId>org.bgee.log4jdbc-log4j2</groupId>
	<artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
	<version>1.16</version> 
</dependency>

logback-spring.xml 설정

출력되는 로그를 설정합니다. /src/main/resources/logback-spring.xml 파일을 신규로 생성하고 아래의 코드를 추가합니다. 실제 운영상태에서는 하단의 <logger name="jdbc" level="OFF" />부분을 수정하여 로그가 다르게 쌓일 수 있도록 설정해야 합니다.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <!--로그 파일 저장 위치-->
    <property name="LOGS_PATH" value="./logs"/>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>%d{HH:mm} %-5level %logger{36} - %msg%n</Pattern>
        </layout>
    </appender>
    <appender name="DAILY_ROLLING_FILE_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOGS_PATH}/logback.log</file>
        <encoder>
            <pattern>[%d{yyyy-MM-dd HH:mm:ss}:%-3relative][%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOGS_PATH}/logback.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <!-- or whenever the file size reaches 100MB -->
                <maxFileSize>5MB</maxFileSize>
                <!-- kb, mb, gb -->
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
    </appender>
    
    <logger name="com.nextday.gateway" level="INFO">
        <appender-ref ref="DAILY_ROLLING_FILE_APPENDER" />
    </logger>
    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
    
    <logger name="jdbc" level="OFF"/>
	<logger name="jdbc.sqlonly" level="OFF"/>
	<logger name="jdbc.sqltiming" level="DEBUG"/>
	<logger name="jdbc.audit" level="OFF"/>
	<logger name="jdbc.resultset" level="OFF"/>
	<logger name="jdbc.resultsettable" level="DEBUG"/>
	<logger name="jdbc.connection" level="OFF"/>
    
</configuration>

log4j. log4jdbc.log4j2.properties 생성하기

log4jdbc.spylogdelegator.name = net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
log4jdbc.dump.sql.maxlinelength = 0

#Disable - Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
log4jdbc.auto.load.popular.drivers = false

jdbc 연결정보 수정

  • driver-class-name 을 net.sf.log4jdbc.sql.jdbcapi.DriverSpy로 변경합니다.
  • 데이터베이스 연결을 jdbc:mysql:// 을 jdbc:log4jdbc:mysql:// 로 변경합니다.
#spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#spring.datasource.oauth.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.datasource.oauth.jdbc-url=jdbc:mysql://host:port/dbname?characterEncoding=UTF-8&serverTimezone=UTC

spring.datasource.oauth.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
spring.datasource.oauth.jdbc-url=jdbc:log4jdbc:mysql://host:port/dbname?characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.oauth.username=user
spring.datasource.oauth.password=password
  • 설정 이후 아래와 같은 경고메시지가 출력됩니다. 실행하는 데는 문제 없으나 아직(2019년 11월 20일 현재)까지 본 오류를 해제하는 방법을 찾지 못했습니다.
    log4jdbc.auto.load.popular.drivers = false로 설정하면 아래의 메시지를 출력하지 않습니다. (댓글을 주신 jk님 감사합니다. 2020년 05월 27일)
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.

설정완료 후 실행 예

log4jdbc 실행 예

 

참고자료

 

728x90