PagingAid -> MapperSupport
parent
936d9e68a3
commit
12fbd09de1
@ -0,0 +1,110 @@
|
|||||||
|
package cokr.xit.foundation.data.paging;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.ibatis.executor.Executor;
|
||||||
|
import org.apache.ibatis.executor.resultset.ResultSetHandler;
|
||||||
|
import org.apache.ibatis.mapping.MappedStatement;
|
||||||
|
import org.apache.ibatis.mapping.SqlCommandType;
|
||||||
|
import org.apache.ibatis.plugin.Intercepts;
|
||||||
|
import org.apache.ibatis.plugin.Signature;
|
||||||
|
import org.apache.ibatis.session.ResultHandler;
|
||||||
|
import org.apache.ibatis.session.RowBounds;
|
||||||
|
|
||||||
|
import cokr.xit.foundation.AbstractEntity;
|
||||||
|
|
||||||
|
@Intercepts({
|
||||||
|
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
|
||||||
|
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class}),
|
||||||
|
|
||||||
|
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
|
||||||
|
})
|
||||||
|
public class MapperSupport extends MybatisPlugin {
|
||||||
|
private static final ThreadLocal<Pageable.Info> pagingInfo = new ThreadLocal<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object query(Executor executor, MappedStatement mappedStatement, Object obj, RowBounds rowBounds, ResultHandler<?> resultHandler) throws SQLException {
|
||||||
|
Pageable.Info paging = Pageable.Info.create(obj);
|
||||||
|
if (paging != null && paging.isPaging())
|
||||||
|
pagingInfo.set(paging);
|
||||||
|
|
||||||
|
return super.query(executor, mappedStatement, obj, rowBounds, resultHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object handle(ResultSetHandler resultSetHandler, Statement statement) throws SQLException {
|
||||||
|
Object obj = super.handle(resultSetHandler, statement);
|
||||||
|
|
||||||
|
Pageable.Info paging = pagingInfo.get();
|
||||||
|
if (paging != null && (obj instanceof List)) {
|
||||||
|
pagingInfo.remove();
|
||||||
|
|
||||||
|
List<?> list = (List<?>)obj;
|
||||||
|
BoundedList<Object> boundedList = new BoundedList<>();
|
||||||
|
boundedList.setFetchSize(paging.fetchSize);
|
||||||
|
boundedList.addAll(list);
|
||||||
|
if (!boundedList.isEmpty()) {
|
||||||
|
boundedList.setStart((paging.pageNum - 1) * paging.fetchSize);
|
||||||
|
}
|
||||||
|
obj = boundedList;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object update(Executor executor, MappedStatement mappedStatement, Object obj) throws SQLException {
|
||||||
|
setEntityTimestamp(mappedStatement.getSqlCommandType(), obj, null);
|
||||||
|
return super.update(executor, mappedStatement, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||||
|
|
||||||
|
private void setEntityTimestamp(SqlCommandType sqlType, Object arg, String now) {
|
||||||
|
if (isEmpty(arg)) return;
|
||||||
|
|
||||||
|
now = ifEmpty(now, () -> dateFormat.format(new Date()));
|
||||||
|
if (arg instanceof AbstractEntity) {
|
||||||
|
setTimestamp(sqlType, (AbstractEntity)arg, now);
|
||||||
|
} else if (arg instanceof Map<?, ?>) {
|
||||||
|
Map<?, ?> map = (Map<?, ?>)arg;
|
||||||
|
for (Object o: map.values())
|
||||||
|
setEntityTimestamp(sqlType, o, now);
|
||||||
|
} else if (arg instanceof Iterable<?>) {
|
||||||
|
Iterable<?> iterable = (Iterable<?>)arg;
|
||||||
|
for (Object o: iterable)
|
||||||
|
setEntityTimestamp(sqlType, o, now);
|
||||||
|
} else if (arg.getClass().isArray()) {
|
||||||
|
Object[] objs = (Object[])arg;
|
||||||
|
for (Object o: objs)
|
||||||
|
setEntityTimestamp(sqlType, o, now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTimestamp(SqlCommandType sqlType, AbstractEntity entity, String now) {
|
||||||
|
String userID = currentUser().getId();
|
||||||
|
switch (sqlType) {
|
||||||
|
case INSERT:
|
||||||
|
entity.setCreatedBy(userID);
|
||||||
|
entity.setCreatedAt(now);
|
||||||
|
entity.setModifiedBy(userID);
|
||||||
|
entity.setLastModified(now);
|
||||||
|
break;
|
||||||
|
case UPDATE:
|
||||||
|
entity.setModifiedBy(userID);
|
||||||
|
entity.setLastModified(now);
|
||||||
|
break;
|
||||||
|
case DELETE:
|
||||||
|
entity.setRemovedBy(userID);
|
||||||
|
entity.setRemovedAt(now);
|
||||||
|
entity.setUseYN("N");
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,51 +0,0 @@
|
|||||||
package cokr.xit.foundation.data.paging;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Statement;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.ibatis.executor.Executor;
|
|
||||||
import org.apache.ibatis.executor.resultset.ResultSetHandler;
|
|
||||||
import org.apache.ibatis.mapping.MappedStatement;
|
|
||||||
import org.apache.ibatis.plugin.Intercepts;
|
|
||||||
import org.apache.ibatis.plugin.Signature;
|
|
||||||
import org.apache.ibatis.session.ResultHandler;
|
|
||||||
import org.apache.ibatis.session.RowBounds;
|
|
||||||
|
|
||||||
@Intercepts({
|
|
||||||
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
|
|
||||||
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
|
|
||||||
})
|
|
||||||
public class PagingAid extends MybatisPlugin {
|
|
||||||
private static final ThreadLocal<Pageable.Info> pagingInfo = new ThreadLocal<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object query(Executor executor, MappedStatement mappedStatement, Object obj, RowBounds rowBounds, ResultHandler<?> resultHandler) throws SQLException {
|
|
||||||
Pageable.Info paging = Pageable.Info.create(obj);
|
|
||||||
if (paging != null && paging.isPaging())
|
|
||||||
pagingInfo.set(paging);
|
|
||||||
|
|
||||||
return super.query(executor, mappedStatement, obj, rowBounds, resultHandler);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Object handle(ResultSetHandler resultSetHandler, Statement statement) throws SQLException {
|
|
||||||
Object obj = super.handle(resultSetHandler, statement);
|
|
||||||
|
|
||||||
Pageable.Info paging = pagingInfo.get();
|
|
||||||
if (paging != null && (obj instanceof List)) {
|
|
||||||
pagingInfo.remove();
|
|
||||||
|
|
||||||
List<?> list = (List<?>)obj;
|
|
||||||
BoundedList<Object> boundedList = new BoundedList<>();
|
|
||||||
boundedList.setFetchSize(paging.fetchSize);
|
|
||||||
boundedList.addAll(list);
|
|
||||||
if (!boundedList.isEmpty()) {
|
|
||||||
boundedList.setStart((paging.pageNum - 1) * paging.fetchSize);
|
|
||||||
}
|
|
||||||
obj = boundedList;
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,166 +0,0 @@
|
|||||||
package cokr.xit.foundation.data.paging;
|
|
||||||
|
|
||||||
import java.sql.Statement;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.ibatis.executor.Executor;
|
|
||||||
import org.apache.ibatis.executor.resultset.ResultSetHandler;
|
|
||||||
import org.apache.ibatis.mapping.MappedStatement;
|
|
||||||
import org.apache.ibatis.mapping.SqlCommandType;
|
|
||||||
import org.apache.ibatis.plugin.Interceptor;
|
|
||||||
import org.apache.ibatis.plugin.Intercepts;
|
|
||||||
import org.apache.ibatis.plugin.Invocation;
|
|
||||||
import org.apache.ibatis.plugin.Signature;
|
|
||||||
import org.apache.ibatis.session.ResultHandler;
|
|
||||||
import org.apache.ibatis.session.RowBounds;
|
|
||||||
|
|
||||||
import cokr.xit.foundation.AbstractComponent;
|
|
||||||
import cokr.xit.foundation.AbstractEntity;
|
|
||||||
import cokr.xit.foundation.component.QueryRequest;
|
|
||||||
|
|
||||||
/**조회 결과의 페이징 처리를 지원하는 MyBatis Interceptor
|
|
||||||
* @author mjkhan
|
|
||||||
*/
|
|
||||||
@Intercepts({
|
|
||||||
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
|
|
||||||
@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
|
|
||||||
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
|
|
||||||
})
|
|
||||||
public class PagingSupport extends AbstractComponent implements Interceptor {
|
|
||||||
private boolean paging;
|
|
||||||
private int pageNum;
|
|
||||||
private int fetchSize;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object intercept(Invocation invocation) throws Throwable {
|
|
||||||
Object[] args = invocation.getArgs();
|
|
||||||
Object arg0 = args[0];
|
|
||||||
if (arg0 instanceof MappedStatement) {
|
|
||||||
MappedStatement stmt = (MappedStatement)arg0;
|
|
||||||
SqlCommandType sqlType = stmt.getSqlCommandType();
|
|
||||||
switch (sqlType) {
|
|
||||||
case SELECT: return setPaging(invocation);
|
|
||||||
case INSERT:
|
|
||||||
case UPDATE:
|
|
||||||
case DELETE: return setEntityProperties(invocation, sqlType);
|
|
||||||
default: return invocation.proceed();
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
switch (getStep(invocation)) {
|
|
||||||
case "ResultSetHandler.handleResultSets": return setPagingInfo(invocation);
|
|
||||||
default: return invocation.proceed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
|
|
||||||
|
|
||||||
private Object setEntityProperties(Invocation invocation, SqlCommandType sqlType) throws Exception {
|
|
||||||
Object[] args = invocation.getArgs();
|
|
||||||
Object arg = args[1];
|
|
||||||
setEntityProperties(sqlType, arg, null);
|
|
||||||
|
|
||||||
return invocation.proceed();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setEntityProperties(SqlCommandType sqlType, Object obj, String now) {
|
|
||||||
if (isEmpty(obj)) return;
|
|
||||||
|
|
||||||
now = ifEmpty(now, () -> dateFormat.format(new Date()));
|
|
||||||
if (obj instanceof AbstractEntity) {
|
|
||||||
setProperties(sqlType, (AbstractEntity)obj, now);
|
|
||||||
} else if (obj instanceof Map<?, ?>) {
|
|
||||||
Map<?, ?> map = (Map<?, ?>)obj;
|
|
||||||
for (Object o: map.values())
|
|
||||||
setEntityProperties(sqlType, o, now);
|
|
||||||
} else if (obj instanceof Iterable<?>) {
|
|
||||||
Iterable<?> iterable = (Iterable<?>)obj;
|
|
||||||
for (Object o: iterable)
|
|
||||||
setEntityProperties(sqlType, o, now);
|
|
||||||
} else if (obj.getClass().isArray()) {
|
|
||||||
Object[] objs = (Object[])obj;
|
|
||||||
for (Object o: objs)
|
|
||||||
setEntityProperties(sqlType, o, now);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setProperties(SqlCommandType sqlType, AbstractEntity entity, String now) {
|
|
||||||
String userID = currentUser().getId();
|
|
||||||
switch (sqlType) {
|
|
||||||
case INSERT:
|
|
||||||
entity.setCreatedBy(userID);
|
|
||||||
entity.setCreatedAt(now);
|
|
||||||
entity.setModifiedBy(userID);
|
|
||||||
entity.setLastModified(now);
|
|
||||||
break;
|
|
||||||
case UPDATE:
|
|
||||||
entity.setModifiedBy(userID);
|
|
||||||
entity.setLastModified(now);
|
|
||||||
break;
|
|
||||||
case DELETE:
|
|
||||||
entity.setRemovedBy(userID);
|
|
||||||
entity.setRemovedAt(now);
|
|
||||||
entity.setUseYN("N");
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Class<?>[] handlers = {Executor.class, ResultSetHandler.class};
|
|
||||||
|
|
||||||
private String getStep(Invocation invocation) {
|
|
||||||
Object obj = invocation.getTarget();
|
|
||||||
String result = "";
|
|
||||||
for (Class<?> klass: handlers) {
|
|
||||||
if (klass.isInstance(obj)) {
|
|
||||||
result = klass.getSimpleName();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result += "." + invocation.getMethod().getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object setPaging(Invocation invocation) throws Exception {
|
|
||||||
Object[] args = invocation.getArgs();
|
|
||||||
Object arg = args[1];
|
|
||||||
if (arg instanceof Map) {
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Map<String, ?> params = (Map<String, ?>)arg;
|
|
||||||
fetchSize = Pageable.getFetchSize(params);
|
|
||||||
pageNum = Pageable.getPageNum(params);
|
|
||||||
} else if (arg instanceof QueryRequest) {
|
|
||||||
QueryRequest req = (QueryRequest)arg;
|
|
||||||
fetchSize = req.getFetchSize();
|
|
||||||
pageNum = req.getPageNum();
|
|
||||||
} else if (arg instanceof Pageable) {
|
|
||||||
Pageable pageable = (Pageable)arg;
|
|
||||||
fetchSize = pageable.getFetchSize();
|
|
||||||
pageNum = pageable.getPageNum();
|
|
||||||
}
|
|
||||||
paging = pageNum > 0 && fetchSize > 0;
|
|
||||||
|
|
||||||
return invocation.proceed();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object setPagingInfo(Invocation invocation) throws Exception {
|
|
||||||
Object obj = invocation.proceed();
|
|
||||||
|
|
||||||
if (paging && (obj instanceof List)) {
|
|
||||||
List<?> list = (List<?>)obj;
|
|
||||||
BoundedList<Object> boundedList = new BoundedList<>();
|
|
||||||
boundedList.setFetchSize(fetchSize);
|
|
||||||
boundedList.addAll(list);
|
|
||||||
if (!boundedList.isEmpty()) {
|
|
||||||
boundedList.setStart((pageNum - 1) * fetchSize);
|
|
||||||
}
|
|
||||||
obj = boundedList;
|
|
||||||
}
|
|
||||||
|
|
||||||
paging = false;
|
|
||||||
pageNum = fetchSize = 0;
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue