Spring4 Mybatis 쿼리 로그 남기는 방법에 대해서 문의드립니다.

조회수 22495회

이클립스에서 spring 4.25 RELEASE버전으로 spring-webmvc legacy 프로젝트를 생성하였습니다. 디비 접속 정보는 WAS에서 관리하기 위해 META-INF에 JNDI 설정 정보를 넣어 놨고, 디비와 연동은 현재 잘 테스트가 되었습니다.

쿼리 로그를 출력하기 위해서 log4j.xml 설정을 건드려봤는데 잘 해결이 되지 않아서 질문 드립니다. 스프링 레거시 프로젝트의 디펜더시를 보니 slf4j를 사용하는거 같은데 log4j.xml도 기본으로 만들어져 있어서 로거가 어떤식으로 동작하는지 잘 이해가 되지 않습니다..

다시 짧게 요약을 하자면 아래와 같습니다.

  1. WAS(Tomcat)에서 JNDI를 이용하여 디비 접속 중
  2. Spring - Mybatis 연동 됨
  3. 쿼리 로그 출력 안됨

mybatis 설정 경로는 아래와 같이 하였습니다.

  • src/main/resources
    • mybatis
      • mapper.xml
      • mybatis-config.xml (마이바티스 설정파일)

[mybatis-config.xml]

<?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="logImpl" value="LOG4J" />
    </settings>

    <typeAliases>
    </typeAliases>
</configuration>

JNDI 설정은 아래와 같이 했습니다.

  • src/main/webapp
    • META-INF
      • context.xml (JNDI 설정파일)

[context.xml]

<?xml version="1.0" encoding="UTF-8"?>
<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>

    <Resource
        auth = "Container"
        driverClassName = "oracle.jdbc.driver.OracleDriver"
        url = "[URL]"
        username = "[ID]"
        password = "[PASSWORD]"
        name = "jdbc/Oracle11g"
        type = "javax.sql.DataSource"
        factory = "org.apache.tomcat.jdbc.pool.DataSourceFactory"
        maxActive = "100" 
        minIdle = "10"
        maxWait = "10000"
        initialSize = "10"
        validationQuery = "SELECT 1 FROM DUAL"
        defaultAutoCommit = "false"
    />
</Context>

web.xml 파일에는 JNDI 정보를 연결했습니다.

  • /src/main/webapp/WEB-INF
    • web.xml
...
<resource-ref>
    <res-ref-name>jdbc/Oracle11g</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>
...

스프링에서 공유해서 사용할 JNDI를 root-context.xml에 만들었습니다.

  • /src/main/webapp/WEB-INF/spring
    • root-context.xml

[root-context.xml]

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <jee:jndi-lookup id="dataSource" jndi-name="jdbc/Oracle11g" resource-ref="true" />

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
        <property name="mapperLocations">
            <list>
                <value>classpath:mybatis/mapper.xml</value>
            </list>
        </property>
    </bean>

    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
        <constructor-arg ref="sqlSessionFactory" />
    </bean>
</beans>

log4j.xml 설정파일에는 아래와 같이 추가했습니다. 아래 설정한 것 외에 java.sql로 시작하는 것도 해봤는데 실패했습니다..

  • src/main/resource
    • log4j.xml

[log4j.xml]

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

    <!-- Appenders -->
    <appender name="console" class="org.apache.log4j.ConsoleAppender">
        <param name="Target" value="System.out" />
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%-5p: %c - %m%n" />
        </layout>
    </appender>

    <!-- Application Loggers -->
    <logger name="[패키지명]">
        <level value="debug" />
    </logger>

    <logger name="jdbc.sqlonly">
        <level value="debug" />
    </logger>

    <logger name="jdbc.sqltiming">
        <level value="debug" />
    </logger>

    <logger name="jdbc.audit">
        <level value="debug" />
    </logger>

    <logger name="jdbc.resultset">
        <level value="debug" />
    </logger>

    <!-- 3rdparty Loggers -->
    <logger name="org.springframework.core">
        <level value="info" />
    </logger>

    <logger name="org.springframework.beans">
        <level value="info" />
    </logger>

    <logger name="org.springframework.context">
        <level value="info" />
    </logger>

    <logger name="org.springframework.web">
        <level value="info" />
    </logger>

    <!-- Root Logger -->
    <root>
        <priority value="warn" />
        <appender-ref ref="console" />
    </root>

</log4j:configuration>

Maven은 아래와 같이 되어 있습니다.
[pom.xml]

<dependencies>
    <!-- Spring -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${org.springframework-version}</version>
        <exclusions>
            <!-- Exclude Commons Logging in favor of SLF4j -->
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
             </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</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.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${org.springframework-version}</version>
        <scope>test</scope>
    </dependency>

    <!-- AspectJ -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>${org.aspectj-version}</version>
    </dependency>   

    <!-- Logging -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${org.slf4j-version}</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>${org.slf4j-version}</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>${org.slf4j-version}</version>
        <scope>runtime</scope>
    </dependency>

    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.15</version>
        <exclusions>
            <exclusion>
                <groupId>javax.mail</groupId>
                <artifactId>mail</artifactId>
            </exclusion>
            <exclusion>
                <groupId>javax.jms</groupId>
                <artifactId>jms</artifactId>
            </exclusion>
            <exclusion>
                <groupId>com.sun.jdmk</groupId>
                <artifactId>jmxtools</artifactId>
            </exclusion>
            <exclusion>
                <groupId>com.sun.jmx</groupId>
                <artifactId>jmxri</artifactId>
            </exclusion>
        </exclusions>
        <scope>runtime</scope>
    </dependency>

    <!-- @Inject -->
    <dependency>
        <groupId>javax.inject</groupId>
        <artifactId>javax.inject</artifactId>
        <version>1</version>
    </dependency>

    <!-- Servlet -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>

    <!-- Test -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>

    <!-- SQL Mapper -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.3.0</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.2.3</version>
    </dependency>
</dependencies>

2 답변

  • 좋아요

    1

    싫어요
    채택 취소하기

    링크 1,링크 2를 참고해보세요.

    [root-context.xml]

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:jee="http://www.springframework.org/schema/jee"
        xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.2.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!-- id를 dataSourceOrigin으로 수정 -->
        <jee:jndi-lookup id="dataSourceOrigin" jndi-name="jdbc/Oracle11g" resource-ref="true" />
    
        <!-- 추가하는 부분 -->
        <bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource">
            <constructor-arg ref="dataSourceOrigin" />
            <property name="logFormatter">
                <bean class="net.sf.log4jdbc.tools.Log4JdbcCustomFormatter">
                    <!-- <property name="loggingType" value="MULTI_LINE" />  --><!-- 여러줄에 출력하려고 하시면 코멘트 해제 -->
                    <property name="sqlPrefix" value="SQL         :  "/>
                </bean>
            </property>
        </bean>
    
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
            <property name="mapperLocations">
                <list>
                    <value>classpath:mybatis/mapper.xml</value>
                </list>
            </property>
        </bean>
    
        <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
            <constructor-arg ref="sqlSessionFactory" />
        </bean>
    </beans>
    

    [pom.xml]에 다음 라이브러리 추가.

    <dependency>
        <groupId>org.lazyluke</groupId>
        <artifactId>log4jdbc-remix</artifactId>
        <version>0.2.7</version>
    </dependency>
    
    • 우선 친절하고 빠른 답변 감사합니다. 잘 동작합니다. 저도 저 첫번째 블로그를 보긴 했지만, 적용을 안했던 이유는 org.lazyluke 그룹을 처음 봤고, 기본 추가된 라이브러리로 가능할 거라고 생각하여 제외했던 부분이라 적용을 안했던 부분인데, 기본 라이브러리로 가능한 방법이 있는지는 사용해보면서 차차 발견해보도록 하겠습니다. 감사합니다! Developer 2016.4.15 18:31
  • Mybatis 3.1까지는 java.sql.Connection, java.sql.PreparedStatement를 logger name로 지정해서 로그레벨을 debug로 선언해야했습니다. Mybatis 3.2부터는 mybatis에서 지정하는 namespace별로 로그레벨을 지정할 수 있습니다. (관련 commmit : https://github.com/mybatis/mybatis-3/commit/84f31e22b3e50641f61b98b59f25b6eac7f93051 )

    예를 들면 아래와 같은 mapper 선언이 있다고 하면

    <mapper namespace="com.ksug.mybatis">
        <insert id="createTable">
            CREATE TABLE user (id INT, name VARCHAR(20))
        </insert>
    </mapper>
    

    위의 mapper에 대한 로깅선언은 아래와 같이 선언해주면 됩니다.

    <logger name="com.ksug.mybatis" level="debug" />
    

    logger name에 쿼리의 ID까지포함할수도 있습니다.

    log4jdbc 같은 SQL로깅만을 위한 라이브러리를 쓰기보다는 개발환경에서의 로깅은 각각의 프레임워크의 정책에 따라 로그레벨 조정으로, 운영환경에서는 Pinpoint, Jeniffer같은 APM을 이용해서 SQL에 대한 추적을 하는 것이 바람직합니다.

    • (•́ ✖ •̀)
      알 수 없는 사용자

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)