Created
January 8, 2019 16:28
-
-
Save circlee/f96dde8908ff77f7b6adf739548b2e48 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Slf4j | |
@Intercepts ( | |
{ | |
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}) | |
} | |
) | |
@Component | |
public class UpdateInterceptor implements Interceptor { | |
ObjectMapper paramObjectMapper; | |
// spring 에서 파라미터 객체 json 출력을 위해 ObjectMapper 생성 | |
@PostConstruct | |
public void init() { | |
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); | |
// 날짜 관련 serializer 추가 | |
builder.serializerByType(LocalDate.class, new com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer(DateTimeFormatter.ofPattern(DateConstans.DATE))); | |
builder.serializerByType(LocalDateTime.class, new com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DateConstans.DATE_TIME))); | |
// empty bean fail 처리 disable | |
builder.featuresToDisable(SerializationFeature.FAIL_ON_EMPTY_BEANS); | |
// 파라미터 객체의 jsonIgnore 된 필드도 출력하기 위한 처리 | |
builder.annotationIntrospector(new JacksonAnnotationIntrospector() { | |
@Override | |
protected boolean _isIgnorable(Annotated a) { | |
return false; | |
} | |
}); | |
paramObjectMapper = builder.build(); | |
} | |
@Override | |
public Object intercept(Invocation invocation) throws Throwable { | |
Object[] args = invocation.getArgs(); | |
MappedStatement ms = (MappedStatement)args[0]; | |
Object param = (Object)args[1]; | |
BoundSql boundSql = ms.getBoundSql(param); | |
log.debug("파라미터 바인딩 SQL : {}", getParameterBindingSQL(boundSql, param)); | |
log.debug("파라미터 JSON : {}" , getParam(param)); | |
return invocation.proceed(); | |
} | |
// 파라미터 sql 바인딩 처리 | |
public String getParameterBindingSQL(BoundSql boundSql, Object parameterObject) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, JsonProcessingException { | |
StringBuilder sqlStringBuilder = new StringBuilder(boundSql.getSql()); | |
// stringBuilder 파라미터 replace 처리 | |
BiConsumer<StringBuilder, Object> sqlObjectReplace = (sqlSb, value) -> { | |
int questionIdx = sqlSb.indexOf("?"); | |
if(questionIdx == -1) { | |
return; | |
} | |
if(value == null) { | |
sqlSb.replace(questionIdx, questionIdx + 1, "null"); | |
} else if (value instanceof String) { | |
sqlSb.replace(questionIdx, questionIdx + 1, "'" + (value != null ? value.toString() : "") + "'"); | |
} else if(value instanceof Integer || value instanceof Long || value instanceof Float || value instanceof Double) { | |
sqlSb.replace(questionIdx, questionIdx + 1, value.toString()); | |
} else if(value instanceof LocalDate || value instanceof LocalDateTime) { | |
sqlSb.replace(questionIdx, questionIdx + 1, "'" + (value != null ? value.toString() : "") + "'"); | |
} else if(value instanceof Enum<?>) { | |
sqlSb.replace(questionIdx, questionIdx + 1, "'" + (value != null ? value.toString() : "") + "'"); | |
} else { | |
sqlSb.replace(questionIdx, questionIdx + 1, value.toString()); | |
} | |
}; | |
if(parameterObject == null) { | |
sqlObjectReplace.accept(sqlStringBuilder, null); | |
} else { | |
if(parameterObject instanceof Integer || parameterObject instanceof Long || parameterObject instanceof Float || parameterObject instanceof Double || parameterObject instanceof String) { | |
sqlObjectReplace.accept(sqlStringBuilder, parameterObject); | |
} else if(parameterObject instanceof Map) { | |
Map paramterObjectMap = (Map)parameterObject; | |
List<ParameterMapping> paramMappings = boundSql.getParameterMappings(); | |
for (ParameterMapping parameterMapping : paramMappings) { | |
String propertyKey = parameterMapping.getProperty(); | |
try { | |
Object paramValue = null; | |
if(boundSql.hasAdditionalParameter(propertyKey)) { | |
// 동적 SQL로 인해 __frch_item_0 같은 파라미터가 생성되어 적재됨, additionalParameter로 획득 | |
paramValue = boundSql.getAdditionalParameter(propertyKey); | |
} else { | |
paramValue = paramterObjectMap.get(propertyKey); | |
} | |
sqlObjectReplace.accept(sqlStringBuilder, paramValue); | |
} catch (Exception e) { | |
sqlObjectReplace.accept(sqlStringBuilder, "[cannot binding : " + propertyKey+ "]"); | |
} | |
} | |
} else { | |
List<ParameterMapping> paramMappings = boundSql.getParameterMappings(); | |
Class< ? extends Object> paramClass = parameterObject.getClass(); | |
for (ParameterMapping parameterMapping : paramMappings) { | |
String propertyKey = parameterMapping.getProperty(); | |
try { | |
Object paramValue = null; | |
if(boundSql.hasAdditionalParameter(propertyKey)) { | |
// 동적 SQL로 인해 __frch_item_0 같은 파라미터가 생성되어 적재됨, additionalParameter로 획득 | |
paramValue = boundSql.getAdditionalParameter(propertyKey); | |
} else { | |
Field field = ReflectionUtils.findField(paramClass, propertyKey); | |
field.setAccessible(true); | |
paramValue = field.get(parameterObject); | |
} | |
sqlObjectReplace.accept(sqlStringBuilder, paramValue); | |
} catch (Exception e) { | |
sqlObjectReplace.accept(sqlStringBuilder, "[cannot binding : " + propertyKey+ "]"); | |
} | |
} | |
} | |
} | |
return sqlStringBuilder.toString(); | |
} | |
private String getParam(final Object parameter) throws Exception { | |
return paramObjectMapper.writeValueAsString(parameter); | |
} | |
@Override | |
public Object plugin(Object target) { | |
return Plugin.wrap(target, this); | |
} | |
@Override | |
public void setProperties(Properties properties) { | |
// TODO Auto-generated method stub | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment