상세 컨텐츠

본문 제목

Mybatis Plugin - Interceptor

Spring/DB 설정

by Chan.94 2022. 10. 24. 08:05

본문

반응형

Mybatis Plugin

Mybatis 플러그인 기능은 AOP와 비슷하게 동작한다. 특정 인터페이스의 메소드를 지정하면 그 인터페이스의 메소드가 실행되지 직전에 플러그인으로 등록한 클래스가 호출된다. AOP처럼 특정 메소드를 언제 어디서 어떻게 호출할지를 정할 수 있으며 수행하기 전과 후에 부가적인 기능을 넣을 수 있다.

 

Mybatis에서 제공해주는 Plugins 클래스는 아래와 같다.

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

 

Mybatis Plugin 설정

@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws IOException {
	SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        
	factoryBean.setPlugins(new DynamicSQLInterceptor());	//Mybatis Plug-In 설정
        
	factoryBean.setDataSource(dataSource);
	factoryBean.setConfigLocation(applicationContext.getResource("classpath:/mybatis/mybatis-config.xml"));
	factoryBean.setMapperLocations(applicationContext.getResources("classpath:/mapper/**/*Mapper.xml"));
	return factoryBean;
}

 

ibatis에서 제공하는 @Intercepts라는 어노테이션을 지정하고, Interceptor 인터페이의 intercept(Invocation invocation) 메서드를 구현해야한다.

 

Property 내용
type Plugin 클래스가 들어가는 자리.
Executor, ParameterHandler, ResultSetHandler, StatementHandler
method 각각의 type에서 제공하는 인터셉터 구간을 지정한다.
StatementHandler 의 경우 (prepare, parameterize, batch, update, query) 
args 각각의 type들은 인터페이스 형태로 되어있는데 method들에 대한 추상메서드들이 있다. 추상메서드의 파라미터값을 넣는다.

 

@Intercepts({
@Signature(type= StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
@Signature(type= StatementHandler.class, method = "parameterize", args = {Statemennt.class})
})

인터셉터는 여러 개 지정할 수 있다. 예를 들어 StatementHandler 타입으로 prepare, parameterize 작업 중에 가로채고 싶다면 아래와 같이 설정한다.

 

@Intercepts

  • 해당 클래스가 Mybatis의 플러그인을 뜻하는 어노테이션이다.
  • 내부적으로 다시 @Signature 애노테이션을 가지고 있다.

@Signature

  • 플러그인과 함께 수행될 인터페이스 메소드를 지정하는 어노테이션이다.

 

 public Object intercept(Invocation invocation) throws Throwable {
   // pre processing
   Object returnObject = invocation.proceed();
   // post processing
   return returnObject;
 }

Spring AOP와 비슷할 것이다. Invocation은 Mybatis가 Interceptor 한 대상정보가 들어가 있다.

Interceptor 하여 전처리, 후처리 프로세스를 추가할 수 있다.

StatementHandler

package org.apache.ibatis.executor.statement;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.session.ResultHandler;

/**
 * @author Clinton Begin
 */
public interface StatementHandler {

  Statement prepare(Connection connection, Integer transactionTimeout)
      throws SQLException;

  void parameterize(Statement statement)
      throws SQLException;

  void batch(Statement statement)
      throws SQLException;

  int update(Statement statement)
      throws SQLException;

  <E> List<E> query(Statement statement, ResultHandler resultHandler)
      throws SQLException;

  <E> Cursor<E> queryCursor(Statement statement)
      throws SQLException;

  BoundSql getBoundSql();

  ParameterHandler getParameterHandler();

}

메소드 prepare, parameterize, batch, update에 대한 내용은 아래 블로그를 참조 바란다. 잘 정리되어있다.

https://aridom.tistory.com/m/71

 

Mybatis StatementHandler와 Batch타입 처리 관련 이슈

이전장(aridom.tistory.com/72)에서 Mybatis Plugins라는것을 알아봤다. 이번에는 Mybatis Plugins 중 하나인 StatementHandler를 이용하면서 발생된 이슈와 이놈이 무슨역할을 하는지 알아보도록 하자. StatementHandler

aridom.tistory.com


Mybatis Interceptor Example

package com.crocodile.mpm.common.interceptort;

import java.sql.Connection;
import java.util.Properties;

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Intercepts(
	{@Signature
	(type = StatementHandler.class
	, method = "prepare"
	, args = {Connection.class, Integer.class})})
public class DynamicSQLInterceptor implements Interceptor{
	
	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
		MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
    
		//Interceptor한 SQL
		String originalSql = (String) metaStatementHandler.getValue("delegate.boundSql.sql");
        
		//파라미터
		Object paramObj = statementHandler.getParameterHandler().getParameterObject();
        
		StringBuffer sql = new StringBuffer();
		sql.append("SELECT *\n");
		sql.append("FROM (\n");
		sql.append(originalSql);
		sql.append("\t)\n");

		//변경된 SQL 설정
		metaStatementHandler.setValue("delegate.boundSql.sql", sql.toString());        
		return invocation.proceed();
	}

	//파라미터로 전달받는 target객체는 실제 타겟이 되는 대상으로 현재 플러그인과 연결해 준다.
	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {
		
	}

}
반응형

'Spring > DB 설정' 카테고리의 다른 글

SpringBoot logback 파일적재  (2) 2021.10.27
SpringBoot logback / log4jdbc 설정  (4) 2021.10.19
Spring JPA란  (1) 2021.10.17
Spring AOP Transaction설정  (0) 2021.10.16
[DBCP] HikariCP  (8) 2021.10.12

관련글 더보기

댓글 영역

>