Mybatis는 꼭 스프링이 아니더라도 스프링 뿐만아니라 다른 언어와도 결합할 수 있는 프레임워크이기 때문에 배워둔다면 스프링 프레임워크가 아닌 다른언어로 웹 어 플리케이션을 제작할때도 활용할수 있는 추가 프레임워크이다.
기본적으로 JDBC 객체들을 개발자가 직접 관여하지 않고 내부적으로 관리해져
sql문에만 집중할 수 있게 해 아주 편하다.
예전 스프링버전 3.0이전일 때는
SqlSessionTemplate
을 사용해서 Mybatis를 사용하였다.
하지만 스프링버전 3.0버전부터 인터페이스 Mapper 어노테이션을 활용한
MapperInterface
방식을 사용할 수 있다.
마이바티스를 사용했을때 어떠한 방식에 구해받지않고 공통적인 장점을 두가지를 나열해 보겠습니다.
- 쿼리문을 수행해주는 PreparedStatement를 직접생성하지않고 해당 기능이 내부적으로 자동으로 처리됩니다.
?
처리마저도 #{필드명} 매핑을통해서 자동으로 처리가 됩니다- RowMapper로 익명클래스를쓰느니 내부클래스를 쓰느니 했던것들을 mybatis가 내부적으로 다 처리해줘서 간편함을 얻을 수 있습니다.
gradle dependency
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0'
application.yml
# mybatis xml파일 경로 설정 경로설정
mybatis:
mapper-locations: classpath:mapper/*.xml
Mybatis sql문이 들어있는 xml 파일 경로를 설정해주는 것이다.
resources
내에서 만드는 것이니 이 경로대로 mapper xml 파일을 잘 만들어주자.
resources > mapper > XXX.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.example.dsg_lms.admin.mapper.CategoryMapper">
<select id="select" resultType="com.example.dsg_lms.admin.dto.CategoryDto">
select c.*
, (select count(*) from course where category_id = c.id) as course_count
from category c
where 1=1
and using_yn = 1
order by sort_value desc
</select>
</mapper>
👀 참고) <ResultMap>
ResultMap으로 mybatis-config.xml에 미리 선언된 객체를 참조하여 다시한번 객체 별칭화를 시켜주며, Mapper NameSpace와 일치하는 인터페이스와 연결해줄 수 있다. DAO클래스역할을 Mapper xml파일이 대신 해주는것과 함께 Java Beans 파일의 프로퍼티와 DB table 컬럼들을 확실하게 매핑하기 위함이 크다
.
예시
<resultMap id="boardVO" type="com.example.board_springboot.domain.BoardVO">
<result property="id" column="id" javaType="Long" jdbcType="BIGINT"/>
<result property="category" column="category" javaType="String" jdbcType="VARCHAR"/>
<result property="password" column="password" javaType="String" jdbcType="VARCHAR"/>
<result property="title" column="title" javaType="String" jdbcType="VARCHAR"/>
<result property="content" column="content" javaType="String" jdbcType="VARCHAR"/>
<result property="writer" column="writer" javaType="String" jdbcType="VARCHAR"/>
<result property="hit" column="hit" javaType="int" jdbcType="INTEGER"/>
<result property="fileYN" column="file_yn" javaType="boolean" jdbcType="INTEGER"/>
<result property="createdAt" column="created_at" javaType="java.sql.Timestamp" jdbcType="TIMESTAMP"/>
<result property="updatedAt" column="updated_at" javaType="java.sql.Timestamp" jdbcType="TIMESTAMP"/>
</resultMap>
src > main > java > com.example.dsg
mapper > XXXMapper 파일
@Mapper
어노테이션을 붙여서 DAO역할의 Mapper 인터페이스 파일을 만들어준다.
이 mapper 파일이 DAO, Repository 파일이라고 생각하면 된다.
예시
@Mapper
public interface CategoryMapper {
List<CategoryDto> select(CategoryDto parameter);
}
호출
예시
Service
@Override
public List<CategoryDto> frontList(CategoryDto parameter) {
return categoryMapper.select(parameter);
}
gradle dependency
implementation 'org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16'
src/main/resources 패키지 경로에 log4jdbc.log4j2.properties
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator
application.yml
-> driver-class-name, url 변경
driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
url: jdbc:log4jdbc:mysql://접속정보~~~~
설정파일은 logback or log4j2.xml 아니면 application.yml 에 설정할 수 있다.
1) logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 로그 경로 변수 선언 -->
<property name="LOG_DIR" value="${user.home}/logs/app" />
<property name="LOG_PATH" value="${LOG_DIR}/app.log"/>
<!-- log4jdbc 옵션 설정 -->
<logger name="jdbc" level="OFF"/>
<!-- connection open close 로깅 여부 -->
<logger name="jdbc.connection" level="OFF"/>
<!-- SQL문만 로깅할지 여부 -->
<logger name="jdbc.sqlonly" level="OFF"/>
<!-- 쿼리문 수행에 걸린 시간 로깅 -->
<logger name="jdbc.sqltiming" level="DEBUG"/>
<!-- ResultSet외 모든 JDBC 호출 정보를 로깅할지 여부 -->
<logger name="jdbc.audit" level="OFF"/>
<!-- ResultSet 포함 모든 JDBC 호출 정보를 로깅 -->
<logger name="jdbc.resultset" level="OFF"/>
<logger name="jdbc.resultsettable" level="INFO"/>
<!-- use Spring default values -->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<!-- 콘솔 출력 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- SQL 결과 조회된 데이터의 table을 로그로 남긴다. -->
<logger name="jdbc.resultsettable" level="ON" additivity="false">
<appender-ref ref="CONSOLE"/>
</logger>
<!-- Rolling File Appender -->
<appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 파일 경로 -->
<file>${LOG_PATH}</file>
<!-- 출력패턴 -->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS}[%-5level] : %msg%n</pattern>
</encoder>
<!-- Rolling 정책 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- .gz,.zip 등을 넣으면 자동으로 일자별 로그파일 압축 -->
<fileNamePattern>${LOG_DIR}/app_%d{yyyy-MM-dd}_%i.log.gz</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- 파일당 최고 용량 10MB -->
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 일자별 로그파일 최대 보관주기(일단위) 만약 해당 설정일 이상된 파일은 자동으로 제거-->
<maxHistory>60</maxHistory>
</rollingPolicy>
</appender>
<root level="INFO"> <!-- DEBUG -->
<appender-ref ref="CONSOLE"/> <!-- 콘솔 출력 -->
<appender-ref ref="ROLLING_FILE"/> <!-- 파일 출력 -->
</root>
</configuration>
2) application.yml
# log4jdbc, Mybatis Console Log
logging:
level:
com:
zaxxer:
hikari: INFO
javax:
sql:
DataSource: OFF
jdbc:
audit: OFF
resultset: OFF
resultsettable: INFO #SQL 결과 데이터 Table을 로그로 남긴다.
sqlonly: OFF #SQL만 로그로 남긴다.
sqltiming: INFO #SQL과 소요시간을 표기한다.
connection : OFF # 커넥션 확인가능
org:
hibernate:
SQL: DEBUG
type:
descriptor:
sql:
BasicBinder: TRACE
- jdbc.sqlonly - SQL 문을 보여준다.
- jdbc.sqltiming - SQL 문과 이 SQL 문을 수행하는 시간(ms)을 같이 보여준다.
- jdbc.audit - ResultSet 을 제외한 모든 JDBC 호출 정보를 로그로 보여준다. 상당히 많은 양의 로그가 나오기 때문에 권장하지 않음.
- jdbc.resultset - ResultSet 을 포함한 모든 JDBC 호출 정보를 로그로 보여준다. audit 처럼 많은 로그가 나오기 때문에 권장하지 않음.
- jdbc.resultsettable - SQL 의 결과로 조회된 데이터를 table 형태로 로그를 보여준다.
- jdbc.connection - DB 연결, 연결 해제와 관련된 로그를 보여준다