Compare commits
2 Commits
main
...
main-pagin
| Author | SHA1 | Date |
|---|---|---|
|
|
8329f3fed0 | 12 months ago |
|
|
7b89f0e96d | 12 months ago |
@ -0,0 +1,75 @@
|
||||
package com.xit.core.mybatis;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.ibatis.executor.parameter.*;
|
||||
import org.apache.ibatis.mapping.*;
|
||||
import org.apache.ibatis.parsing.*;
|
||||
import org.apache.ibatis.scripting.xmltags.*;
|
||||
import org.apache.ibatis.session.*;
|
||||
|
||||
import lombok.*;
|
||||
import lombok.extern.slf4j.*;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Mybatis sql logging
|
||||
* mybatis.configuration.default-scripting-language=com.xit.core.support.mybatis.MybatisLanguageDriver
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
public class MybatisLanguageDriver extends XMLLanguageDriver {
|
||||
public MybatisLanguageDriver() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
|
||||
addDebuggingComment(boundSql);
|
||||
return super.createParameterHandler(mappedStatement, parameterObject, boundSql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {
|
||||
return super.createSqlSource(configuration, script, parameterType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType) {
|
||||
return super.createSqlSource(configuration, script, parameterType);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
private void addDebuggingComment(BoundSql boundSql) {
|
||||
Field sqlField = BoundSql.class.getDeclaredField("sql");
|
||||
sqlField.setAccessible(true);
|
||||
|
||||
String sql = (String) sqlField.get(boundSql);
|
||||
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
|
||||
sql = addParameterComment(sql, parameterMappings);
|
||||
|
||||
sqlField.set(boundSql, sql);
|
||||
}
|
||||
|
||||
private String addParameterComment(String sql, List<ParameterMapping> parameters) {
|
||||
StringBuilder sqlInternalStringBuilder = new StringBuilder(sql);
|
||||
|
||||
int paramReverseIndex = parameters.size() - 1;
|
||||
for (int idx = sql.length() - 1; idx > 0; idx--) {
|
||||
char c = sql.charAt(idx);
|
||||
if (c == '?') {
|
||||
String commentedString = toCommentString(parameters.get(paramReverseIndex).getProperty());
|
||||
|
||||
sqlInternalStringBuilder.insert(idx + 1, commentedString);
|
||||
paramReverseIndex = paramReverseIndex - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return sqlInternalStringBuilder.toString();
|
||||
}
|
||||
|
||||
private String toCommentString(String comment) {
|
||||
return " /*" + comment + "*/ ";
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
package com.xit.core.mybatis;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.egovframe.rte.ptl.mvc.tags.ui.pagination.*;
|
||||
import org.springframework.context.annotation.*;
|
||||
|
||||
import com.xit.core.mybatis.paging.util.*;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* description : For Pagination Tag
|
||||
* packageName : com.xit.core.mybatis
|
||||
* fileName : MybatisPagiRenderConfig
|
||||
* author : limju
|
||||
* date : 2024 12월 31
|
||||
* ======================================================================
|
||||
* 변경일 변경자 변경 내용
|
||||
* ----------------------------------------------------------------------
|
||||
* 2024 12월 31 limju 최초 생성
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Configuration
|
||||
public class MybatisPagiRenderConfig {
|
||||
@Bean
|
||||
public XitPaginationRenderer xitPaginationRenderer(){
|
||||
return new XitPaginationRenderer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PaginationManager xitPaginationManager(){
|
||||
Map<String, PaginationRenderer> rendererType = new HashMap<>();
|
||||
rendererType.put("user", xitPaginationRenderer());
|
||||
|
||||
DefaultPaginationManager paginationManager = new DefaultPaginationManager();
|
||||
paginationManager.setRendererType(rendererType);
|
||||
return paginationManager;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package com.xit.core.mybatis;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.ibatis.type.*;
|
||||
|
||||
public class ObjectTypeHandler extends BaseTypeHandler<Object> {
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
|
||||
throws SQLException {
|
||||
ps.setObject(i, parameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
Object value = "";
|
||||
Object object = rs.getObject(columnName);
|
||||
value = object;
|
||||
if(object instanceof Clob) {
|
||||
|
||||
Clob clob = (Clob) object;
|
||||
|
||||
if (clob != null) {
|
||||
try {
|
||||
int size = (int) clob.length();
|
||||
value = clob.getSubString(1, size);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (object instanceof java.sql.Date ) {
|
||||
Timestamp sqlTimestamp = rs.getTimestamp(columnName);
|
||||
if (sqlTimestamp != null) {
|
||||
value = new Date(sqlTimestamp.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getNullableResult(ResultSet rs, int columnIndex)
|
||||
throws SQLException {
|
||||
Object value = "";
|
||||
Object object = rs.getObject(columnIndex);
|
||||
value = object;
|
||||
if(object instanceof Clob) {
|
||||
|
||||
Clob clob = (Clob) object;
|
||||
|
||||
if (clob != null) {
|
||||
try {
|
||||
int size = (int) clob.length();
|
||||
value = clob.getSubString(1, size);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (object instanceof java.sql.Date ) {
|
||||
Timestamp sqlTimestamp = rs.getTimestamp(columnIndex);
|
||||
if (sqlTimestamp != null) {
|
||||
value = new Date(sqlTimestamp.getTime());
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getNullableResult(CallableStatement cs, int columnIndex)
|
||||
throws SQLException {
|
||||
return cs.getObject(columnIndex);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,208 @@
|
||||
package com.xit.core.mybatis;
|
||||
|
||||
import java.nio.charset.*;
|
||||
|
||||
import org.apache.ibatis.plugin.*;
|
||||
|
||||
import com.fasterxml.jackson.core.*;
|
||||
import com.fasterxml.jackson.databind.*;
|
||||
|
||||
public class PagingConstants {
|
||||
|
||||
public static final String KEY_OP_MODE = "spring.profiles.active";
|
||||
public static final String OP_MODE_DEFAULT = "local";
|
||||
|
||||
// RestTemplate 상수
|
||||
public static final int CONNECT_TIMEOUT = 30 * 1000; // 30초
|
||||
public static final int READ_TIMEOUT = 60 * 1000 * 3; // 3분
|
||||
public static final Charset CHARSET = StandardCharsets.UTF_8;
|
||||
public static final String DEFAULT_VIEW = ViewName.JSON_VIEW.getCode();
|
||||
|
||||
/**
|
||||
* CustomCommonsRequestLoggingFilter에서 로깅을 제외할 url 패턴 정의
|
||||
*/
|
||||
public static final String EXCLUDE_LOGGING_URL_PATTERN = "^(/webjars/|/swagger-ui/|/swagger-resources|/v2/api-docs|/h2-console)"; // "^(/webjars/|/sample/|/web/)"
|
||||
|
||||
public enum ActiveProfile {
|
||||
LOCAL("local"),
|
||||
DEV("dev"),
|
||||
STG("stg"),
|
||||
PROD("prod"),
|
||||
TEST("test");
|
||||
|
||||
private final String code;
|
||||
|
||||
ActiveProfile(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 인증정보 저장 방식
|
||||
*
|
||||
*/
|
||||
public enum AuthSaveType {
|
||||
SECURITY("security"), // SessionCreationPolicy.STATELESS인 경우는 SecurityContext 사용불가
|
||||
SESSION("session"), // TOKEN도 사용 가능은 하지만...
|
||||
HEADER("header"); // TOKEN
|
||||
|
||||
private final String code;
|
||||
|
||||
AuthSaveType(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
|
||||
public enum JwtToken {
|
||||
// 토큰헤더명,
|
||||
HEADER_NAME("Authorization"),
|
||||
GRANT_TYPE("Bearer"),
|
||||
ACCESS_TOKEN_NAME("accessToken"),
|
||||
REFRESH_TOKEN_NAME("refreshToken"),
|
||||
AUTHORITIES_KEY("role"),
|
||||
TOKEN_USER_NAME("userName"),
|
||||
TOKEN_USER_MAIL("userEmail"),
|
||||
TOKEN_USER_ID("userId");
|
||||
|
||||
private final String code;
|
||||
|
||||
JwtToken(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JWT Token 통신 방식 지정
|
||||
* COOKIE : accessToken - header, refreshToken - cookie
|
||||
* HEADER : accessToken - header, refreshToken - DTO
|
||||
* DTO : accessToken - header, refreshToken - DTO
|
||||
*/
|
||||
public enum JwtTokenParamType {
|
||||
COOKIE,
|
||||
HEADER,
|
||||
DTO
|
||||
}
|
||||
|
||||
public enum ViewName{
|
||||
JSON_VIEW("mappingJackson2JsonView")
|
||||
;
|
||||
private String code;
|
||||
|
||||
ViewName(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* mybatis paging 처리시 return list root attribute name
|
||||
* @see PageListJsonSerializer#serialize(PageList, JsonGenerator, SerializerProvider)
|
||||
*/
|
||||
public static final String RSLT_ATTR_NAME = "_item_";
|
||||
|
||||
/**
|
||||
* Maybatis / jpa 페이지 정보 저장
|
||||
* @see OffsetLimitInterceptor#intercept(Invocation)
|
||||
* @see Paginator#setSessionPagination(Paginator)
|
||||
* @see kr.xit.fims.framework.support.jpa.Paginator#setSessionPagination(com.xit.core.support.jpa.Paginator)
|
||||
*/
|
||||
public enum Session {
|
||||
PAGE_INFO("_pageInfo_"),
|
||||
// DATASET_NAME("gds_pageInfo"),
|
||||
/** 세션에 저장되는 인증유저 객체 attribute name */
|
||||
AuthentSessionObject("AUTH_SS_OBJECT"),
|
||||
/** 세션에 저장되는 인증유저 권한종류 attribute name */
|
||||
AuthentSessionAuthority("AUTH_SS_AUTHORITY"),
|
||||
;
|
||||
|
||||
private String code;
|
||||
|
||||
Session( String code ) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
|
||||
public enum LoginType {
|
||||
SSO,
|
||||
Login,
|
||||
Unknown
|
||||
}
|
||||
|
||||
public enum CharsetType {
|
||||
Default("default"),
|
||||
Utf8( "UTF-8" ),
|
||||
EucKr( "EUC-KR" ),
|
||||
Iso8859("8859_1");
|
||||
|
||||
private String code;
|
||||
|
||||
CharsetType( String code) {
|
||||
this.code = code;
|
||||
}
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public Charset getCharset() {
|
||||
if ( this == Default )
|
||||
return Charset.defaultCharset();
|
||||
|
||||
return Charset.forName( this.code);
|
||||
}
|
||||
|
||||
public byte[] getBytes( String str ) {
|
||||
return str.getBytes( this.getCharset() );
|
||||
}
|
||||
|
||||
public String getString( byte[] bytes ) {
|
||||
return new String( bytes, this.getCharset() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* String pad처리 시 추가문자 지정타입
|
||||
* @타입 : PadType
|
||||
*/
|
||||
public enum PadType {
|
||||
/** 문자열 왼쪽 */
|
||||
Left,
|
||||
/** 문자열 오른쪽 */
|
||||
Right
|
||||
}
|
||||
|
||||
public enum PageNavigator {
|
||||
DIV_ID("pager"),
|
||||
CLASS_NAME("pager"),
|
||||
FIRST_SYMBOLIC(" ◀ "),
|
||||
PREV_SYMBOLIC(" ◁ "),
|
||||
NEXT_SYMBOLIC(" ▷ "),
|
||||
LAST_SYMBOLIC(" ▶ ");
|
||||
|
||||
private String code;
|
||||
|
||||
PageNavigator(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,167 @@
|
||||
package com.xit.core.mybatis;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.*;
|
||||
|
||||
import org.apache.commons.logging.*;
|
||||
import org.apache.ibatis.session.*;
|
||||
import org.mybatis.spring.*;
|
||||
import org.springframework.beans.factory.*;
|
||||
import org.springframework.core.io.*;
|
||||
|
||||
/**
|
||||
* mybatis mapper 자동 감지 후 자동으로 서버 재시작이 필요 없이 반영
|
||||
*/
|
||||
public class RefreshableSqlSessionFactoryBean extends SqlSessionFactoryBean implements DisposableBean {
|
||||
private static final Log log = LogFactory.getLog(RefreshableSqlSessionFactoryBean.class);
|
||||
private SqlSessionFactory proxy;
|
||||
private int interval = 500;
|
||||
private Timer timer;
|
||||
private TimerTask task;
|
||||
private Resource[] mapperLocations;
|
||||
/**
|
||||
* 파일 감시 쓰레드가 실행중인지 여부.
|
||||
*/
|
||||
private boolean running = false;
|
||||
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
|
||||
private final Lock r = rwl.readLock();
|
||||
private final Lock w = rwl.writeLock();
|
||||
|
||||
public void setMapperLocations(Resource[] mapperLocations) {
|
||||
super.setMapperLocations(mapperLocations);
|
||||
this.mapperLocations = mapperLocations;
|
||||
}
|
||||
|
||||
public void setInterval(int interval) {
|
||||
this.interval = interval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public void refresh() throws Exception {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("refreshing sqlMapClient.");
|
||||
}
|
||||
w.lock();
|
||||
try {
|
||||
super.afterPropertiesSet();
|
||||
} finally {
|
||||
w.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 싱글톤 멤버로 SqlMapClient 원본 대신 프록시로 설정하도록 오버라이드.
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
super.afterPropertiesSet();
|
||||
setRefreshable();
|
||||
}
|
||||
|
||||
private void setRefreshable() {
|
||||
proxy = (SqlSessionFactory) Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[] { SqlSessionFactory.class }, new InvocationHandler() {
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
// log.debug("method.getName() : " + method.getName());
|
||||
return method.invoke(getParentObject(), args);
|
||||
}
|
||||
});
|
||||
task = new TimerTask() {
|
||||
private final Map<Resource, Long> map = new HashMap<>();
|
||||
|
||||
public void run() {
|
||||
if (isModified()) {
|
||||
try {
|
||||
refresh();
|
||||
} catch (Exception e) {
|
||||
log.error("caught exception", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isModified() {
|
||||
boolean retVal = false;
|
||||
if (mapperLocations != null) {
|
||||
for (int i = 0; i < mapperLocations.length; i++) {
|
||||
Resource mappingLocation = mapperLocations[i];
|
||||
retVal |= findModifiedResource(mappingLocation);
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private boolean findModifiedResource(Resource resource) {
|
||||
boolean retVal = false;
|
||||
List<String> modifiedResources = new ArrayList<String>();
|
||||
try {
|
||||
long modified = resource.lastModified();
|
||||
if (map.containsKey(resource)) {
|
||||
long lastModified = (Long) map.get(resource);
|
||||
if (lastModified != modified) {
|
||||
map.put(resource, modified);
|
||||
modifiedResources.add(resource.getDescription());
|
||||
retVal = true;
|
||||
}
|
||||
} else {
|
||||
map.put(resource, modified);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error("caught exception", e);
|
||||
}
|
||||
if (retVal) {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("modified files : " + modifiedResources);
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
};
|
||||
timer = new Timer(true);
|
||||
resetInterval();
|
||||
}
|
||||
|
||||
private Object getParentObject() throws Exception {
|
||||
r.lock();
|
||||
try {
|
||||
return super.getObject();
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public SqlSessionFactory getObject() {
|
||||
return this.proxy;
|
||||
}
|
||||
|
||||
public Class<? extends SqlSessionFactory> getObjectType() {
|
||||
return (this.proxy != null ? this.proxy.getClass() : SqlSessionFactory.class);
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setCheckInterval(int ms) {
|
||||
interval = ms;
|
||||
if (timer != null) {
|
||||
resetInterval();
|
||||
}
|
||||
}
|
||||
|
||||
private void resetInterval() {
|
||||
if (running) {
|
||||
timer.cancel();
|
||||
running = false;
|
||||
}
|
||||
if (interval > 0) {
|
||||
timer.schedule(task, 0, interval);
|
||||
running = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() throws Exception {
|
||||
timer.cancel();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
package com.xit.core.mybatis.paging;
|
||||
|
||||
import javax.servlet.*;
|
||||
|
||||
public class CleanupMybatisPaginatorListener implements ServletContextListener {
|
||||
public void contextInitialized(ServletContextEvent servletContextEvent) {
|
||||
|
||||
}
|
||||
|
||||
public void contextDestroyed(ServletContextEvent servletContextEvent) {
|
||||
OffsetLimitInterceptor.Pool.shutdownNow();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,210 @@
|
||||
package com.xit.core.mybatis.paging;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import org.apache.commons.lang3.*;
|
||||
import org.apache.ibatis.cache.*;
|
||||
import org.apache.ibatis.executor.Executor;
|
||||
import org.apache.ibatis.mapping.*;
|
||||
import org.apache.ibatis.mapping.MappedStatement.*;
|
||||
import org.apache.ibatis.plugin.*;
|
||||
import org.apache.ibatis.session.*;
|
||||
import org.slf4j.*;
|
||||
import org.springframework.web.context.request.*;
|
||||
|
||||
import com.xit.core.mybatis.*;
|
||||
import com.xit.core.mybatis.paging.dialect.*;
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
import com.xit.core.mybatis.paging.support.*;
|
||||
|
||||
import lombok.extern.slf4j.*;
|
||||
|
||||
/**
|
||||
* Paging 정보 - Paginator(page, limit, totalcount)- 획득, 추가
|
||||
*/
|
||||
@Slf4j
|
||||
@Intercepts({ @Signature(type = Executor.class,
|
||||
method = "query",
|
||||
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }) })
|
||||
public class OffsetLimitInterceptor implements Interceptor {
|
||||
//private final Logger log = LoggerHelper.getLogger();
|
||||
static int MAPPED_STATEMENT_INDEX = 0;
|
||||
static int PARAMETER_INDEX = 1;
|
||||
static int ROWBOUNDS_INDEX = 2;
|
||||
//static int RESULT_HANDLER_INDEX = 3;
|
||||
static ExecutorService Pool;
|
||||
String dialectClass;
|
||||
boolean asyncTotalCount = false;
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public Object intercept(final Invocation invocation) throws Throwable {
|
||||
final Executor executor = (Executor) invocation.getTarget();
|
||||
final Object[] queryArgs = invocation.getArgs();
|
||||
final MappedStatement ms = (MappedStatement) queryArgs[MAPPED_STATEMENT_INDEX];
|
||||
final Object parameter = queryArgs[PARAMETER_INDEX];
|
||||
final RowBounds rowBounds = (RowBounds) queryArgs[ROWBOUNDS_INDEX];
|
||||
final PageBounds pageBounds = new PageBounds(rowBounds);
|
||||
if (pageBounds.getOffset() == RowBounds.NO_ROW_OFFSET && pageBounds.getLimit() == RowBounds.NO_ROW_LIMIT && pageBounds.getOrders().isEmpty()) {
|
||||
return invocation.proceed();
|
||||
}
|
||||
|
||||
final Dialect dialect;
|
||||
try {
|
||||
Class clazz = Class.forName(dialectClass);
|
||||
Constructor constructor = clazz.getConstructor(MappedStatement.class, Object.class, PageBounds.class);
|
||||
dialect = (Dialect) constructor.newInstance(new Object[] { ms, parameter, pageBounds });
|
||||
} catch (Exception e) {
|
||||
throw new ClassNotFoundException("Cannot create dialect instance: " + dialectClass, e);
|
||||
}
|
||||
|
||||
final BoundSql boundSql = ms.getBoundSql(parameter);
|
||||
|
||||
queryArgs[MAPPED_STATEMENT_INDEX] = copyFromNewSql(ms, boundSql, dialect.getPageSQL(), dialect.getParameterMappings(), dialect.getParameterObject());
|
||||
queryArgs[PARAMETER_INDEX] = dialect.getParameterObject();
|
||||
queryArgs[ROWBOUNDS_INDEX] = new RowBounds(RowBounds.NO_ROW_OFFSET, RowBounds.NO_ROW_LIMIT);
|
||||
|
||||
boolean async = pageBounds.getAsyncTotalCount() == null ? asyncTotalCount : pageBounds.getAsyncTotalCount();
|
||||
Future<List> listFuture = call((Callable<List>) () -> (List) invocation.proceed(), async);
|
||||
|
||||
if (pageBounds.isContainsTotalCount()) {
|
||||
Callable<Paginator> countTask = (Callable) () -> {
|
||||
Paginator paginator;
|
||||
Integer count;
|
||||
Cache cache = ms.getCache();
|
||||
if (cache != null && ms.isUseCache() && ms.getConfiguration().isCacheEnabled()) {
|
||||
CacheKey cacheKey = executor.createCacheKey(
|
||||
ms,
|
||||
parameter,
|
||||
new PageBounds(),
|
||||
copyFromBoundSql(ms, boundSql, dialect.getCountSQL(), boundSql.getParameterMappings(), boundSql.getParameterObject()));
|
||||
count = (Integer) cache.getObject(cacheKey);
|
||||
if (count == null) {
|
||||
count = SQLHelp.getCount(ms, parameter, boundSql, dialect);
|
||||
cache.putObject(cacheKey, count);
|
||||
}
|
||||
} else {
|
||||
count = SQLHelp.getCount(ms, parameter, boundSql, dialect);
|
||||
}
|
||||
paginator = new Paginator(pageBounds.getPage(), pageBounds.getLimit(), count);
|
||||
return paginator;
|
||||
};
|
||||
Future<Paginator> countFutrue = call(countTask, async);
|
||||
// PageList pageList = new PageList(listFuture.get(), countFutrue.get());
|
||||
|
||||
// log.debug("###################################################################################");
|
||||
// log.debug("OffsetLimitInterceptor Page information ThreadLocal save::{} - {}", FEnum.Session.PAGE_INFO.getValue(), countFutrue.get());
|
||||
// log.debug("###################################################################################");
|
||||
RequestContextHolder.currentRequestAttributes().setAttribute(PagingConstants.Session.PAGE_INFO.getCode(), countFutrue.get(), RequestAttributes.SCOPE_REQUEST);
|
||||
// ContextThreadLocalHolder.setPageListThreadLocal(pageList);
|
||||
// return pageList; return new PageList(listFuture.get(), countFutrue.get());
|
||||
}
|
||||
return listFuture.get();
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private <T> Future<T> call(Callable callable, boolean async) {
|
||||
if (async) {
|
||||
return Pool.submit(callable);
|
||||
} else {
|
||||
FutureTask<T> future = new FutureTask(callable);
|
||||
future.run();
|
||||
return future;
|
||||
}
|
||||
}
|
||||
|
||||
private MappedStatement copyFromNewSql(MappedStatement ms, BoundSql boundSql, String sql, List<ParameterMapping> parameterMappings, Object parameter) {
|
||||
BoundSql newBoundSql = copyFromBoundSql(ms, boundSql, sql, parameterMappings, parameter);
|
||||
return copyFromMappedStatement(ms, new BoundSqlSqlSource(newBoundSql));
|
||||
}
|
||||
|
||||
private BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, String sql, List<ParameterMapping> parameterMappings, Object parameter) {
|
||||
BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), sql, parameterMappings, parameter);
|
||||
for (ParameterMapping mapping : boundSql.getParameterMappings()) {
|
||||
String prop = mapping.getProperty();
|
||||
if (boundSql.hasAdditionalParameter(prop)) {
|
||||
newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));
|
||||
}
|
||||
}
|
||||
return newBoundSql;
|
||||
}
|
||||
|
||||
// see: MapperBuilderAssistant
|
||||
private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource) {
|
||||
Builder builder = new Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType());
|
||||
builder.resource(ms.getResource());
|
||||
builder.fetchSize(ms.getFetchSize());
|
||||
builder.statementType(ms.getStatementType());
|
||||
builder.keyGenerator(ms.getKeyGenerator());
|
||||
if (ObjectUtils.isNotEmpty(ms.getKeyProperties())) {
|
||||
StringBuilder keyProperties = new StringBuilder();
|
||||
for (String keyProperty : ms.getKeyProperties()) {
|
||||
keyProperties.append(keyProperty).append(",");
|
||||
}
|
||||
keyProperties.delete(keyProperties.length() - 1, keyProperties.length());
|
||||
builder.keyProperty(keyProperties.toString());
|
||||
}
|
||||
|
||||
// setStatementTimeout()
|
||||
builder.timeout(ms.getTimeout());
|
||||
|
||||
// setStatementResultMap()
|
||||
builder.parameterMap(ms.getParameterMap());
|
||||
|
||||
// setStatementResultMap()
|
||||
builder.resultMaps(ms.getResultMaps());
|
||||
builder.resultSetType(ms.getResultSetType());
|
||||
|
||||
// setStatementCache()
|
||||
builder.cache(ms.getCache());
|
||||
builder.flushCacheRequired(ms.isFlushCacheRequired());
|
||||
builder.useCache(ms.isUseCache());
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public Object plugin(Object target) {
|
||||
return Plugin.wrap(target, this);
|
||||
}
|
||||
|
||||
public void setProperties(Properties properties) {
|
||||
PropertiesHelper propertiesHelper = new PropertiesHelper(properties);
|
||||
String dialectClass = propertiesHelper.getRequiredString("dialectClass");
|
||||
setDialectClass(dialectClass);
|
||||
setAsyncTotalCount(propertiesHelper.getBoolean("asyncTotalCount", false));
|
||||
setPoolMaxSize(propertiesHelper.getInt("poolMaxSize", 0));
|
||||
}
|
||||
|
||||
public static class BoundSqlSqlSource implements SqlSource {
|
||||
BoundSql boundSql;
|
||||
|
||||
public BoundSqlSqlSource(BoundSql boundSql) {
|
||||
this.boundSql = boundSql;
|
||||
}
|
||||
|
||||
public BoundSql getBoundSql(Object parameterObject) {
|
||||
return boundSql;
|
||||
}
|
||||
}
|
||||
|
||||
public void setDialectClass(String dialectClass) {
|
||||
//logger.debug("dialectClass: {} ", dialectClass);
|
||||
this.dialectClass = dialectClass;
|
||||
}
|
||||
|
||||
public void setAsyncTotalCount(boolean asyncTotalCount) {
|
||||
//logger.debug("asyncTotalCount: {} ", asyncTotalCount);
|
||||
this.asyncTotalCount = asyncTotalCount;
|
||||
}
|
||||
|
||||
public void setPoolMaxSize(int poolMaxSize) {
|
||||
|
||||
if (poolMaxSize > 0) {
|
||||
log.debug("poolMaxSize: {} ", poolMaxSize);
|
||||
Pool = Executors.newFixedThreadPool(poolMaxSize);
|
||||
} else {
|
||||
Pool = Executors.newCachedThreadPool();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
package com.xit.core.mybatis.paging.dialect;
|
||||
|
||||
import org.apache.ibatis.mapping.*;
|
||||
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
public class DB2Dialect extends Dialect {
|
||||
|
||||
public DB2Dialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
private static String getRowNumber(String sql) {
|
||||
StringBuilder rownumber = new StringBuilder(50)
|
||||
.append("rownumber() over(");
|
||||
|
||||
int orderByIndex = sql.toLowerCase().indexOf("order by");
|
||||
|
||||
if (orderByIndex > 0 && !hasDistinct(sql)) {
|
||||
rownumber.append(sql.substring(orderByIndex));
|
||||
}
|
||||
|
||||
rownumber.append(") as rownumber_,");
|
||||
|
||||
return rownumber.toString();
|
||||
}
|
||||
|
||||
private static boolean hasDistinct(String sql) {
|
||||
return sql.toLowerCase().contains("select distinct");
|
||||
}
|
||||
|
||||
protected String getLimitString(String sql, String offsetName, int offset,
|
||||
String limitName, int limit) {
|
||||
int startOfSelect = sql.toLowerCase().indexOf("select");
|
||||
|
||||
StringBuilder pagingSelect = new StringBuilder(sql.length() + 100)
|
||||
.append(sql, 0, startOfSelect) // add the comment
|
||||
.append("select * from ( select ") // nest the main query in an
|
||||
// outer select
|
||||
.append(getRowNumber(sql)); // add the rownnumber bit into the
|
||||
// outer query select list
|
||||
|
||||
if (hasDistinct(sql)) {
|
||||
pagingSelect.append(" row_.* from ( ") // add another (inner) nested
|
||||
// select
|
||||
.append(sql.substring(startOfSelect)) // add the main query
|
||||
.append(" ) as row_"); // close off the inner nested select
|
||||
} else {
|
||||
pagingSelect.append(sql.substring(startOfSelect + 6)); // add the
|
||||
// main
|
||||
// query
|
||||
}
|
||||
|
||||
pagingSelect.append(" ) as temp_ where rownumber_ ");
|
||||
|
||||
// add the restriction to the outer select
|
||||
if (offset > 0) {
|
||||
pagingSelect.append("between ?+1 and ?");
|
||||
setPageParameter(offsetName, offset, Integer.class);
|
||||
setPageParameter("__offsetEnd", offset + limit, Integer.class);
|
||||
} else {
|
||||
pagingSelect.append("<= ?");
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
}
|
||||
|
||||
return pagingSelect.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package com.xit.core.mybatis.paging.dialect;
|
||||
|
||||
import org.apache.ibatis.mapping.*;
|
||||
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
public class DerbyDialect extends Dialect {
|
||||
|
||||
public DerbyDialect(MappedStatement mappedStatement,
|
||||
Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
public boolean supportsLimit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean supportsLimitOffset() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getLimitString(String sql, int offset,
|
||||
String offsetPlaceholder, int limit, String limitPlaceholder) {
|
||||
|
||||
return sql +
|
||||
" offset " + offsetPlaceholder + " rows fetch next "
|
||||
+ limitPlaceholder + " rows only";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,123 @@
|
||||
package com.xit.core.mybatis.paging.dialect;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.ibatis.mapping.*;
|
||||
import org.apache.ibatis.session.*;
|
||||
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
public class Dialect {
|
||||
protected MappedStatement mappedStatement;
|
||||
protected PageBounds pageBounds;
|
||||
protected Object parameterObject;
|
||||
protected BoundSql boundSql;
|
||||
protected List<ParameterMapping> parameterMappings;
|
||||
protected Map<String, Object> pageParameters = new HashMap<String, Object>();
|
||||
|
||||
private String pageSQL;
|
||||
private String countSQL;
|
||||
|
||||
public Dialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
this.mappedStatement = mappedStatement;
|
||||
this.parameterObject = parameterObject;
|
||||
this.pageBounds = pageBounds;
|
||||
init();
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
protected void init() {
|
||||
boundSql = mappedStatement.getBoundSql(parameterObject);
|
||||
parameterMappings = new ArrayList(boundSql.getParameterMappings());
|
||||
if (parameterObject instanceof Map) {
|
||||
pageParameters.putAll((Map) parameterObject);
|
||||
} else {
|
||||
for (ParameterMapping parameterMapping : parameterMappings) {
|
||||
pageParameters.put(parameterMapping.getProperty(), parameterObject);
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder bufferSql = new StringBuilder(boundSql.getSql().trim());
|
||||
if (bufferSql.lastIndexOf(";") == bufferSql.length() - 1) {
|
||||
bufferSql.deleteCharAt(bufferSql.length() - 1);
|
||||
}
|
||||
String sql = bufferSql.toString();
|
||||
pageSQL = sql;
|
||||
if (pageBounds.getOrders() != null && !pageBounds.getOrders().isEmpty()) {
|
||||
pageSQL = getSortString(sql, pageBounds.getOrders());
|
||||
}
|
||||
if (pageBounds.getOffset() != RowBounds.NO_ROW_OFFSET || pageBounds.getLimit() != RowBounds.NO_ROW_LIMIT) {
|
||||
pageSQL = getLimitString(pageSQL, "__offset", pageBounds.getOffset(), "__limit", pageBounds.getLimit());
|
||||
}
|
||||
countSQL = getCountString(sql);
|
||||
}
|
||||
|
||||
public List<ParameterMapping> getParameterMappings() {
|
||||
return parameterMappings;
|
||||
}
|
||||
|
||||
public Object getParameterObject() {
|
||||
return pageParameters;
|
||||
}
|
||||
|
||||
public String getPageSQL() {
|
||||
return pageSQL;
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
protected void setPageParameter(String name, Object value, Class type) {
|
||||
ParameterMapping parameterMapping = new ParameterMapping.Builder(mappedStatement.getConfiguration(), name, type).build();
|
||||
parameterMappings.add(parameterMapping);
|
||||
pageParameters.put(name, value);
|
||||
}
|
||||
|
||||
public String getCountSQL() {
|
||||
return countSQL;
|
||||
}
|
||||
|
||||
/**
|
||||
* page query make
|
||||
*
|
||||
* @param sql sql
|
||||
* @param offsetName offsetName
|
||||
* @param offset offset
|
||||
* @param limitName limitName
|
||||
* @param limit limit
|
||||
* @return String query
|
||||
*/
|
||||
protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
|
||||
throw new UnsupportedOperationException("paged queries not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* get total count SQL
|
||||
*
|
||||
* @param sql SQL
|
||||
* @return String count sql
|
||||
*/
|
||||
protected String getCountString(String sql) {
|
||||
return "select count(1) from (\n" + sql + "\n) tmp_count";
|
||||
}
|
||||
|
||||
/**
|
||||
* ordered sql
|
||||
*
|
||||
* @param sql SQL
|
||||
* @param orders ordered field List
|
||||
* @return 정렬구문까지 포함된 sql
|
||||
*/
|
||||
protected String getSortString(String sql, List<Order> orders) {
|
||||
if (orders == null || orders.isEmpty()) {
|
||||
return sql;
|
||||
}
|
||||
|
||||
StringBuilder buffer = new StringBuilder("select * from (\n").append(sql).append("\n) temp_order order by ");
|
||||
for (Order order : orders) {
|
||||
if (order != null) {
|
||||
buffer.append(order.toString()).append(", ");
|
||||
}
|
||||
}
|
||||
buffer.delete(buffer.length() - 2, buffer.length());
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.xit.core.mybatis.paging.dialect;
|
||||
|
||||
import org.apache.ibatis.mapping.*;
|
||||
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
public class H2Dialect extends Dialect {
|
||||
|
||||
public H2Dialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
protected String getLimitString(String sql, String offsetName,int offset, String limitName, int limit) {
|
||||
return sql +
|
||||
((offset > 0) ? " limit " + String.valueOf(limit) + " offset " + String.valueOf(offset) : " limit " + String.valueOf(limit));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.xit.core.mybatis.paging.dialect;
|
||||
|
||||
import org.apache.ibatis.mapping.*;
|
||||
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
public class HSQLDialect extends Dialect {
|
||||
public HSQLDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
|
||||
boolean hasOffset = offset > 0;
|
||||
return new StringBuffer(sql.length() + 10)
|
||||
.append(sql)
|
||||
.insert(sql.toLowerCase().indexOf("select") + 6,
|
||||
hasOffset ? " limit " + String.valueOf(offset) + " " + String.valueOf(limit) : " top " + String.valueOf(limit)).toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package com.xit.core.mybatis.paging.dialect;
|
||||
|
||||
import org.apache.ibatis.mapping.*;
|
||||
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
public class MariaDbDialect extends Dialect {
|
||||
|
||||
public MariaDbDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
|
||||
StringBuilder buffer = new StringBuilder(sql.length() + 20).append(sql);
|
||||
if (offset > 0) {
|
||||
buffer.append("\n limit ?, ?");
|
||||
setPageParameter(offsetName, offset, Integer.class);
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
} else {
|
||||
buffer.append("\n limit ?");
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package com.xit.core.mybatis.paging.dialect;
|
||||
|
||||
import org.apache.ibatis.mapping.*;
|
||||
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
public class MySQLDialect extends Dialect {
|
||||
|
||||
public MySQLDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
|
||||
StringBuilder buffer = new StringBuilder(sql.length() + 20).append(sql);
|
||||
if (offset > 0) {
|
||||
buffer.append("\n limit ?, ?");
|
||||
setPageParameter(offsetName, offset, Integer.class);
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
} else {
|
||||
buffer.append("\n limit ?");
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package com.xit.core.mybatis.paging.dialect;
|
||||
|
||||
import org.apache.ibatis.mapping.*;
|
||||
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
public class OracleDialect extends Dialect {
|
||||
|
||||
public OracleDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
|
||||
sql = sql.trim();
|
||||
boolean isForUpdate = false;
|
||||
if (sql.toLowerCase().endsWith(" for update")) {
|
||||
sql = sql.substring(0, sql.length() - 11);
|
||||
isForUpdate = true;
|
||||
}
|
||||
|
||||
StringBuilder pagingSelect = new StringBuilder(sql.length() + 100);
|
||||
if (offset > 0) {
|
||||
pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
|
||||
} else {
|
||||
pagingSelect.append("select * from ( ");
|
||||
}
|
||||
pagingSelect.append(sql);
|
||||
if (offset > 0) {
|
||||
pagingSelect.append(" ) row_ ) where rownum_ <= ? and rownum_ > ?");
|
||||
setPageParameter("__offsetEnd", offset + limit, Integer.class);
|
||||
setPageParameter(offsetName, offset, Integer.class);
|
||||
} else {
|
||||
pagingSelect.append(" ) where rownum <= ?");
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
}
|
||||
|
||||
if (isForUpdate) {
|
||||
pagingSelect.append(" for update");
|
||||
}
|
||||
|
||||
return pagingSelect.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package com.xit.core.mybatis.paging.dialect;
|
||||
|
||||
import org.apache.ibatis.mapping.*;
|
||||
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
/**
|
||||
* @author badqiu
|
||||
* @author miemiedev
|
||||
*/
|
||||
public class PostgreSQLDialect extends Dialect {
|
||||
|
||||
public PostgreSQLDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
protected String getLimitString(String sql, String offsetName,int offset, String limitName, int limit) {
|
||||
StringBuilder buffer = new StringBuilder( sql.length()+20 ).append(sql);
|
||||
if(offset > 0){
|
||||
buffer.append(" limit ? offset ?");
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
setPageParameter(offsetName, offset, Integer.class);
|
||||
|
||||
}else{
|
||||
buffer.append(" limit ?");
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
package com.xit.core.mybatis.paging.dialect;
|
||||
|
||||
import org.apache.ibatis.mapping.*;
|
||||
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
public class SQLServer2005Dialect extends Dialect {
|
||||
|
||||
public SQLServer2005Dialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a LIMIT clause to the given SQL SELECT
|
||||
* The LIMIT SQL will look like:
|
||||
* WITH query AS (SELECT TOP 100 percent ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __row_number__, * from table_name)
|
||||
* SELECT * FROM query WHERE __row_number__ BETWEEN :offset and :lastRows ORDER BY __row_number__
|
||||
*
|
||||
* @param sql The SQL statement to base the limit query off of.
|
||||
* @param offset Offset of the first row to be returned by the query (zero-based)
|
||||
* @param limit Maximum number of rows to be returned by the query
|
||||
* @return A new SQL statement with the LIMIT clause applied.
|
||||
*/
|
||||
protected String getLimitString(String sql, String offsetName,int offset, String limitName, int limit) {
|
||||
StringBuilder pagingBuilder = new StringBuilder();
|
||||
String orderby = getOrderByPart(sql);
|
||||
String distinctStr = "";
|
||||
|
||||
String loweredString = sql.toLowerCase();
|
||||
String sqlPartString = sql;
|
||||
if (loweredString.trim().startsWith("select")) {
|
||||
int index = 6;
|
||||
if (loweredString.startsWith("select distinct")) {
|
||||
distinctStr = "DISTINCT ";
|
||||
index = 15;
|
||||
}
|
||||
sqlPartString = sqlPartString.substring(index);
|
||||
}
|
||||
pagingBuilder.append(sqlPartString);
|
||||
|
||||
// if no ORDER BY is specified use fake ORDER BY field to avoid errors
|
||||
if (orderby.isEmpty()) {
|
||||
orderby = "ORDER BY CURRENT_TIMESTAMP";
|
||||
}
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append("WITH query AS (SELECT ")
|
||||
.append(distinctStr)
|
||||
.append("TOP 100 PERCENT ")
|
||||
.append(" ROW_NUMBER() OVER (")
|
||||
.append(orderby)
|
||||
.append(") as __row_number__, ")
|
||||
.append(pagingBuilder)
|
||||
.append(") SELECT * FROM query WHERE __row_number__ > ? AND __row_number__ <= ?")
|
||||
.append(" ORDER BY __row_number__");
|
||||
setPageParameter(offsetName,offset,Integer.class);
|
||||
setPageParameter("__offsetEnd",offset+limit,Integer.class);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
static String getOrderByPart(String sql) {
|
||||
String loweredString = sql.toLowerCase();
|
||||
int orderByIndex = loweredString.indexOf("order by");
|
||||
if (orderByIndex != -1) {
|
||||
// if we find a new "order by" then we need to ignore
|
||||
// the previous one since it was probably used for a subquery
|
||||
return sql.substring(orderByIndex);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package com.xit.core.mybatis.paging.dialect;
|
||||
|
||||
import org.apache.ibatis.mapping.*;
|
||||
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
public class SQLServerDialect extends Dialect {
|
||||
|
||||
public SQLServerDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
|
||||
static int getAfterSelectInsertPoint(String sql) {
|
||||
int selectIndex = sql.toLowerCase().indexOf( "select" );
|
||||
final int selectDistinctIndex = sql.toLowerCase().indexOf( "select distinct" );
|
||||
return selectIndex + ( selectDistinctIndex == selectIndex ? 15 : 6 );
|
||||
}
|
||||
|
||||
|
||||
protected String getLimitString(String sql, String offsetName,int offset, String limitName, int limit) {
|
||||
if ( offset > 0 ) {
|
||||
throw new UnsupportedOperationException( "sql server has no offset" );
|
||||
}
|
||||
setPageParameter(limitName, limit, Integer.class);
|
||||
return new StringBuffer( sql.length() + 8 ).append( sql ).insert( getAfterSelectInsertPoint( sql ), " top " + limit ).toString();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package com.xit.core.mybatis.paging.dialect;
|
||||
|
||||
import org.apache.ibatis.mapping.*;
|
||||
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
public class SybaseDialect extends Dialect {
|
||||
|
||||
public SybaseDialect(MappedStatement mappedStatement, Object parameterObject, PageBounds pageBounds) {
|
||||
super(mappedStatement, parameterObject, pageBounds);
|
||||
}
|
||||
|
||||
|
||||
protected String getLimitString(String sql, String offsetName,int offset, String limitName, int limit) {
|
||||
throw new UnsupportedOperationException( "paged queries not supported" );
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,138 @@
|
||||
package com.xit.core.mybatis.paging.domain;//import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||
|
||||
import com.xit.*;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Getter @Setter
|
||||
public class ModelAndViewResponse<T> { //implements IResponse, Serializable {
|
||||
private final static String SUCCESS = "200";
|
||||
private final static String NOT_FOUND = "400";
|
||||
private final static String FAILED = "500";
|
||||
private final static String SUCCESS_MESSAGE = "정상 처리 되었습니다.";
|
||||
private final static String NOT_FOUND_MESSAGE = "NOT FOUND";
|
||||
private final static String FAILED_MESSAGE = "서버에서 오류가 발생하였습니다.";
|
||||
|
||||
private ModelAndViewResponse() {
|
||||
|
||||
}
|
||||
|
||||
private ModelAndViewResponse(T data) {
|
||||
ModelAndView mav = new ModelAndView(XitConstants.DEFAULT_VIEW);
|
||||
mav.addObject("result", true);
|
||||
mav.addObject("message", SUCCESS_MESSAGE);
|
||||
mav.addObject("data", data);
|
||||
|
||||
if(data == null){
|
||||
mav.addObject("count", 0);
|
||||
|
||||
}else {
|
||||
// Pageing 처리
|
||||
|
||||
if (Collection.class.isAssignableFrom(data.getClass())) {
|
||||
mav.addObject("count", (((Collection<?>) data).size()));
|
||||
|
||||
} else {
|
||||
mav.addObject("count", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* return ModelAndView (Grid data)
|
||||
* {
|
||||
* result - true / false
|
||||
* message
|
||||
* data: {
|
||||
* contents - 실행결과 데이타
|
||||
* pagination - 페이징 요청 처리시
|
||||
* }
|
||||
* count - 목록의 수(페이징 요청 처리시는 현재 페이지 목록수)
|
||||
* }
|
||||
* </pre>
|
||||
* @param data
|
||||
* @return
|
||||
* @param <T>
|
||||
*/
|
||||
public static <T> ModelAndView of(T data){
|
||||
ModelAndView mav = new ModelAndView(XitConstants.DEFAULT_VIEW);
|
||||
|
||||
mav.addObject("result", true);
|
||||
mav.addObject("message", SUCCESS_MESSAGE);
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("contents", data);
|
||||
mav.addObject("data", map);
|
||||
|
||||
if(data == null){
|
||||
mav.addObject("count", 0);
|
||||
|
||||
}else {
|
||||
// Pageing 처리
|
||||
|
||||
if (Collection.class.isAssignableFrom(data.getClass())) {
|
||||
mav.addObject("count", (((Collection<?>) data).size()));
|
||||
|
||||
} else {
|
||||
mav.addObject("count", 1);
|
||||
}
|
||||
}
|
||||
return mav;
|
||||
}
|
||||
|
||||
public static <T> ModelAndView of(T data, String viewName){
|
||||
ModelAndView mav = new ModelAndView(viewName);
|
||||
|
||||
mav.addObject("result", true);
|
||||
mav.addObject("message", SUCCESS_MESSAGE);
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("contents", data);
|
||||
mav.addObject("data", map);
|
||||
|
||||
if(data == null){
|
||||
mav.addObject("count", 0);
|
||||
|
||||
}else {
|
||||
// Pageing 처리
|
||||
|
||||
if (Collection.class.isAssignableFrom(data.getClass())) {
|
||||
mav.addObject("count", (((Collection<?>) data).size()));
|
||||
|
||||
} else {
|
||||
mav.addObject("count", 1);
|
||||
}
|
||||
}
|
||||
return mav;
|
||||
}
|
||||
|
||||
public static <T> ModelAndView of(String attName, T data){
|
||||
ModelAndView mav = new ModelAndView(XitConstants.DEFAULT_VIEW);
|
||||
|
||||
mav.addObject("result", true);
|
||||
mav.addObject("message", SUCCESS_MESSAGE);
|
||||
mav.addObject(attName, data);
|
||||
|
||||
if(data == null){
|
||||
mav.addObject("count", 0);
|
||||
|
||||
}else {
|
||||
// Pageing 처리
|
||||
|
||||
if (Collection.class.isAssignableFrom(data.getClass())) {
|
||||
mav.addObject("count", (((Collection<?>) data).size()));
|
||||
|
||||
} else {
|
||||
mav.addObject("count", 1);
|
||||
}
|
||||
}
|
||||
return mav;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,149 @@
|
||||
package com.xit.core.mybatis.paging.domain;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.regex.*;
|
||||
|
||||
import org.apache.commons.lang3.*;
|
||||
|
||||
public class Order implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Direction direction;
|
||||
private String property;
|
||||
private String orderExpr;
|
||||
|
||||
public Order(String property, Direction direction, String orderExpr) {
|
||||
this.direction = direction;
|
||||
this.property = property;
|
||||
this.orderExpr = orderExpr;
|
||||
}
|
||||
|
||||
public Direction getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public String getProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public String getOrderExpr() {
|
||||
return orderExpr;
|
||||
}
|
||||
|
||||
public void setDirection(Direction direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
public void setProperty(String property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public void setOrderExpr(String orderExpr) {
|
||||
this.orderExpr = orderExpr;
|
||||
}
|
||||
|
||||
public static boolean isSQLInjection(String str) {
|
||||
String INJECTION_REGEX = "[A-Za-z0-9\\_\\-\\+\\.]+";
|
||||
return !Pattern.matches(INJECTION_REGEX, str);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (isSQLInjection(property)) {
|
||||
throw new IllegalArgumentException("SQLInjection property: " + property);
|
||||
}
|
||||
if (orderExpr != null && orderExpr.contains("?")) {
|
||||
String[] exprs = orderExpr.split("\\?");
|
||||
if (exprs.length == 2) {
|
||||
return String.format(orderExpr.replaceAll("\\?", "%s"), property) + (direction == null ? "" : " " + direction.name());
|
||||
}
|
||||
return String.format(orderExpr.replaceAll("\\?", "%s"), property, direction == null ? "" : " " + direction.name());
|
||||
}
|
||||
return property + (direction == null ? "" : " " + direction.name());
|
||||
}
|
||||
|
||||
public static List<Order> formString(String orderSegment) {
|
||||
return formString(orderSegment, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param orderSegment String
|
||||
* ex: "id.asc,code.desc" or "code.desc"
|
||||
* @param orderExpr String
|
||||
* @return List<Order> List
|
||||
*/
|
||||
public static List<Order> formString(String orderSegment, String orderExpr) {
|
||||
if (Objects.isNull(orderSegment) || Objects.equals(StringUtils.EMPTY, orderSegment.trim())) {
|
||||
return new ArrayList<Order>(0);
|
||||
}
|
||||
|
||||
List<Order> results = new ArrayList<Order>();
|
||||
String[] orderSegments = orderSegment.trim().split(",");
|
||||
for (int i = 0; i < orderSegments.length; i++) {
|
||||
String sortSegment = orderSegments[i];
|
||||
Order order = _formString(sortSegment, orderExpr);
|
||||
if (order != null) {
|
||||
results.add(order);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private static Order _formString(String orderSegment, String orderExpr) {
|
||||
|
||||
if (Objects.isNull(orderSegment) || Objects.equals(StringUtils.EMPTY, orderSegment.trim())
|
||||
|| orderSegment.startsWith("null.")
|
||||
|| orderSegment.startsWith(".")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] array = orderSegment.trim().split("\\.");
|
||||
if (array.length != 1 && array.length != 2) {
|
||||
throw new IllegalArgumentException(
|
||||
"orderSegment pattern must be {property}.{direction}, input is: " + orderSegment);
|
||||
}
|
||||
|
||||
return create(array[0], array.length == 2 ? array[1] : "asc", orderExpr);
|
||||
}
|
||||
|
||||
public static Order create(String property, String direction) {
|
||||
return create(property, direction, null);
|
||||
}
|
||||
|
||||
/**
|
||||
*<pre>
|
||||
* @param property property
|
||||
* @param direction direction
|
||||
* @param orderExpr
|
||||
* Oracle query에 특정 column의 대소문자 구분없이 정렬 방법 (case-insensitive sort)
|
||||
* placeholder is "?", in oracle like:
|
||||
* "nlssort( ? ,'NLS_SORT=SCHINESE_PINYIN_M')". Warning: you must
|
||||
* prevent orderExpr SQL injection.
|
||||
* Oracle session level에서 "nls_sort"의 값을 다음과 같이 설정함으로서 "nlssort"함수를 번번히 사용할 필요는 없습니다.
|
||||
* SQL: alter session set nls_sort=generic_m_ai;
|
||||
* Session altered.
|
||||
* @return Order Order
|
||||
* </pre>
|
||||
*/
|
||||
public static Order create(String property, String direction, String orderExpr) {
|
||||
return new Order(property, Direction.fromString(direction), orderExpr);
|
||||
}
|
||||
|
||||
/**
|
||||
* PropertyPath implements the pairing of an {@link Direction} and a
|
||||
* property. It is used to provide input for
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public static enum Direction {
|
||||
ASC, DESC;
|
||||
public static Direction fromString(String value) {
|
||||
try {
|
||||
return Direction.valueOf(value.toUpperCase(Locale.US));
|
||||
} catch (Exception e) {
|
||||
return ASC;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,157 @@
|
||||
package com.xit.core.mybatis.paging.domain;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.ibatis.session.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* <pre>
|
||||
* TODO 프로젝트에 맞춰 페이지 정보 내용 define
|
||||
* new PageBounds(limit)
|
||||
* new PageBounds(page, limit)
|
||||
* new PageBounds("field, field")
|
||||
* new PageBounds(page, limit, "field, field.desc")
|
||||
* new PageBounds(page, limit, "field.asc, filed.desc")
|
||||
* @author minuk
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
public class PageBounds extends RowBounds implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public final static int NO_PAGE = 1;
|
||||
protected int page = NO_PAGE;
|
||||
protected int limit = NO_ROW_LIMIT;
|
||||
protected List<Order> orders = new ArrayList<Order>();
|
||||
protected boolean containsTotalCount;
|
||||
protected Boolean asyncTotalCount;
|
||||
|
||||
public PageBounds() {
|
||||
containsTotalCount = false;
|
||||
}
|
||||
|
||||
public PageBounds(RowBounds rowBounds) {
|
||||
if (rowBounds instanceof PageBounds) {
|
||||
PageBounds pageBounds = (PageBounds) rowBounds;
|
||||
this.page = pageBounds.page;
|
||||
this.limit = pageBounds.limit;
|
||||
this.orders = pageBounds.orders;
|
||||
this.containsTotalCount = pageBounds.containsTotalCount;
|
||||
this.asyncTotalCount = pageBounds.asyncTotalCount;
|
||||
} else {
|
||||
this.page = (rowBounds.getOffset() / rowBounds.getLimit()) + 1;
|
||||
this.limit = rowBounds.getLimit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Query TOP N, default containsTotalCount = false
|
||||
* @param limit limit
|
||||
*/
|
||||
public PageBounds(int limit) {
|
||||
this.limit = limit;
|
||||
this.containsTotalCount = false;
|
||||
}
|
||||
|
||||
public PageBounds(int page, int limit) {
|
||||
this(page, limit, new ArrayList<Order>(), true);
|
||||
}
|
||||
|
||||
public PageBounds(int page, int limit, boolean containsTotalCount) {
|
||||
this(page, limit, new ArrayList<Order>(), containsTotalCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Just sorting, default containsTotalCount = false
|
||||
* @param orders orders
|
||||
*/
|
||||
public PageBounds(List<Order> orders) {
|
||||
this(NO_PAGE, NO_ROW_LIMIT, orders, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Just sorting, default containsTotalCount = false
|
||||
* @param order order
|
||||
*/
|
||||
public PageBounds(Order... order) {
|
||||
this(NO_PAGE, NO_ROW_LIMIT, order);
|
||||
this.containsTotalCount = false;
|
||||
}
|
||||
|
||||
public PageBounds(int page, int limit, Order... order) {
|
||||
this(page, limit, Arrays.asList(order), true);
|
||||
}
|
||||
|
||||
public PageBounds(int page, int limit, List<Order> orders) {
|
||||
this(page, limit, orders, true);
|
||||
}
|
||||
|
||||
public PageBounds(int page, int limit, List<Order> orders,
|
||||
boolean containsTotalCount) {
|
||||
this.page = page;
|
||||
this.limit = limit;
|
||||
this.orders = orders;
|
||||
this.containsTotalCount = containsTotalCount;
|
||||
}
|
||||
|
||||
public int getPage() {
|
||||
return page;
|
||||
}
|
||||
|
||||
public void setPage(int page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public int getLimit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
public void setLimit(int limit) {
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
public boolean isContainsTotalCount() {
|
||||
return containsTotalCount;
|
||||
}
|
||||
|
||||
public void setContainsTotalCount(boolean containsTotalCount) {
|
||||
this.containsTotalCount = containsTotalCount;
|
||||
}
|
||||
|
||||
public List<Order> getOrders() {
|
||||
return orders;
|
||||
}
|
||||
|
||||
public void setOrders(List<Order> orders) {
|
||||
this.orders = orders;
|
||||
}
|
||||
|
||||
public Boolean getAsyncTotalCount() {
|
||||
return asyncTotalCount;
|
||||
}
|
||||
|
||||
public void setAsyncTotalCount(Boolean asyncTotalCount) {
|
||||
this.asyncTotalCount = asyncTotalCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOffset() {
|
||||
if (page >= 1) {
|
||||
return (page - 1) * limit;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PageBounds{" + "page=" + page +
|
||||
", limit=" + limit +
|
||||
", orders=" + orders +
|
||||
", containsTotalCount=" + containsTotalCount +
|
||||
", asyncTotalCount=" + asyncTotalCount +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package com.xit.core.mybatis.paging.domain;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class PageList<E> extends ArrayList<E> {
|
||||
private static final long serialVersionUID = 1412759446332294208L;
|
||||
|
||||
private Paginator paginator;
|
||||
|
||||
public PageList() {
|
||||
}
|
||||
|
||||
public PageList(Collection<? extends E> c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
public PageList(Collection<? extends E> c, Paginator p) {
|
||||
super(c);
|
||||
this.paginator = p;
|
||||
}
|
||||
|
||||
public PageList(Paginator p) {
|
||||
this.paginator = p;
|
||||
}
|
||||
|
||||
public Paginator getPaginator() {
|
||||
return paginator;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,142 @@
|
||||
package com.xit.core.mybatis.paging.domain;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import org.springframework.web.context.request.*;
|
||||
|
||||
import com.xit.core.mybatis.*;
|
||||
|
||||
public class Paginator implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final int limit;
|
||||
private int page = 1;
|
||||
private final int totalCount;
|
||||
|
||||
public Paginator(int page, int limit, int totalCount) {
|
||||
super();
|
||||
this.limit = limit;
|
||||
this.totalCount = totalCount;
|
||||
this.page = computePageNo(page);
|
||||
}
|
||||
|
||||
public void setSessionPagination(Paginator paginator){
|
||||
RequestContextHolder.currentRequestAttributes().setAttribute(PagingConstants.Session.PAGE_INFO.getCode(), paginator, RequestAttributes.SCOPE_REQUEST);
|
||||
}
|
||||
|
||||
public int getPage() {
|
||||
return page;
|
||||
}
|
||||
|
||||
public void setPage(int page) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
public int getLimit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
public int getTotalCount() {
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
public boolean isFirstPage() {
|
||||
return page <= 1;
|
||||
}
|
||||
|
||||
public boolean isLastPage() {
|
||||
return page >= getTotalPages();
|
||||
}
|
||||
|
||||
public int getPrePage() {
|
||||
if (isHasPrePage()) {
|
||||
return page - 1;
|
||||
} else {
|
||||
return page;
|
||||
}
|
||||
}
|
||||
|
||||
public int getNextPage() {
|
||||
if (isHasNextPage()) {
|
||||
return page + 1;
|
||||
} else {
|
||||
return page;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDisabledPage(int page) {
|
||||
return ((page < 1) || (page > getTotalPages()) || (page == this.page));
|
||||
}
|
||||
|
||||
public boolean isHasPrePage() {
|
||||
return (page - 1 >= 1);
|
||||
}
|
||||
|
||||
public boolean isHasNextPage() {
|
||||
return (page + 1 <= getTotalPages());
|
||||
}
|
||||
|
||||
public int getStartRow() {
|
||||
if (getLimit() <= 0 || totalCount <= 0)
|
||||
return 0;
|
||||
return page > 0 ? (page - 1) * getLimit() + 1 : 0;
|
||||
}
|
||||
|
||||
public int getEndRow() {
|
||||
return page > 0 ? Math.min(limit * page, getTotalCount()) : 0;
|
||||
}
|
||||
|
||||
public int getOffset() {
|
||||
return page > 0 ? (page - 1) * getLimit() : 0;
|
||||
}
|
||||
|
||||
public int getTotalPages() {
|
||||
if (totalCount <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (limit <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = totalCount / limit;
|
||||
if (totalCount % limit > 0) {
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
protected int computePageNo(int page) {
|
||||
return computePageNumber(page, limit, totalCount);
|
||||
}
|
||||
|
||||
private static int computeLastPageNumber(int totalItems, int pageSize) {
|
||||
if (pageSize <= 0)
|
||||
return 1;
|
||||
int result = (int) (totalItems % pageSize == 0 ? totalItems / pageSize
|
||||
: totalItems / pageSize + 1);
|
||||
if (result <= 1)
|
||||
result = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int computePageNumber(int page, int pageSize, int totalItems) {
|
||||
if (page <= 1) {
|
||||
return 1;
|
||||
}
|
||||
if (Integer.MAX_VALUE == page
|
||||
|| page > computeLastPageNumber(totalItems, pageSize)) { // last
|
||||
// page
|
||||
return computeLastPageNumber(totalItems, pageSize);
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Paginator" +
|
||||
"{page=" + page +
|
||||
", limit=" + limit +
|
||||
", totalCount=" + totalCount +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package com.xit.core.mybatis.paging.jackson2;
|
||||
|
||||
import com.fasterxml.jackson.core.*;
|
||||
import com.fasterxml.jackson.databind.*;
|
||||
import com.fasterxml.jackson.databind.module.*;
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* Converter의 ObjectMapper 확장
|
||||
* ResponseBody 사용시 호출
|
||||
* Converter 실행시 Paging 정보 추가 return
|
||||
* page, limit(row/page), totalCount, offset(쿼리조회시작row), startRow, prePage, nextPage, endRow, totalPages
|
||||
* boolean 값 : firstPage, lastPage, hasPrePage, hasNextPage
|
||||
* </pre>
|
||||
* @author minuk
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class PageListJsonMapper extends ObjectMapper{
|
||||
|
||||
public PageListJsonMapper() {
|
||||
//JSON data pretty 정렬
|
||||
enable(SerializationFeature.INDENT_OUTPUT);
|
||||
SimpleModule module = new SimpleModule("PageListJSONModule", new Version(1, 0, 0, null, null, null));
|
||||
//module.addSerializer(PageList.class, new PageListJsonSerializer(this));
|
||||
module.addSerializer(PageList.class, new PageListJsonSerializer());
|
||||
registerModule(module);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package com.xit.core.mybatis.paging.jackson2;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import org.slf4j.*;
|
||||
|
||||
import com.fasterxml.jackson.core.*;
|
||||
import com.fasterxml.jackson.databind.*;
|
||||
import com.xit.core.mybatis.*;
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
import lombok.extern.slf4j.*;
|
||||
|
||||
//TODO PageListJsonSerializer - Converting시 data attribute name 정의 - property에서 읽어 온다
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Slf4j
|
||||
public class PageListJsonSerializer extends JsonSerializer<PageList>{
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void serialize(PageList value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
|
||||
Paginator paginator = value.getPaginator();
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("totalCount", paginator.getTotalCount());
|
||||
map.put("totalPages", paginator.getTotalPages());
|
||||
map.put("page", paginator.getPage());
|
||||
map.put("limit", paginator.getLimit());
|
||||
// Query Data
|
||||
map.put(PagingConstants.RSLT_ATTR_NAME, new ArrayList(value));
|
||||
// map.put(DEFAULT_RESPONSE_BODY_DATA_NAME, new ArrayList(value));
|
||||
map.put("startRow", paginator.getStartRow());
|
||||
map.put("endRow", paginator.getEndRow());
|
||||
map.put("offset", paginator.getOffset());
|
||||
// map.put("slider", paginator.getSlider());
|
||||
map.put("prePage", paginator.getPrePage());
|
||||
map.put("nextPage", paginator.getNextPage());
|
||||
map.put("firstPage", paginator.isFirstPage());
|
||||
map.put("hasNextPage", paginator.isHasNextPage());
|
||||
map.put("hasPrePage", paginator.isHasPrePage());
|
||||
map.put("lastPage", paginator.isLastPage());
|
||||
|
||||
// mapper.writeValue(jgen, map);
|
||||
jgen.writeObject(map);
|
||||
log.debug("#########################################Paging infomation##########################################################");
|
||||
log.debug("{}", map);
|
||||
log.debug("###################################################################################################");
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,74 @@
|
||||
package com.xit.core.mybatis.paging.springmvc;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import javax.servlet.http.*;
|
||||
|
||||
import org.slf4j.*;
|
||||
import org.springframework.web.context.request.*;
|
||||
import org.springframework.web.servlet.*;
|
||||
import org.springframework.web.servlet.handler.*;
|
||||
|
||||
import com.xit.core.mybatis.*;
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* name+Paginator
|
||||
* ex) ModelAndView.addObject("data", Object) ==> dataPaginator
|
||||
* ResponseBody 형태의 call이 아닌경우 Paging 정보를 추가하여 return
|
||||
* TODO PageListAttrHandlerInterceptor - @ResponseBody 형태의 call인 경우는 정보 추가 불가 - 필요시 이 부분 처리 필요
|
||||
* TODO PageListAttrHandlerInterceptor - 페이지 정보 setting name 정의 - - property에서 읽어 온다
|
||||
* </pre>
|
||||
*/
|
||||
public class PageListAttrHandlerInterceptor extends HandlerInterceptorAdapter {
|
||||
|
||||
public boolean preHandle(HttpServletRequest request,
|
||||
HttpServletResponse httpServletResponse, Object o) throws Exception {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object handler, ModelAndView mav) throws Exception {
|
||||
|
||||
Object pageObject = RequestContextHolder.getRequestAttributes().getAttribute(PagingConstants.Session.PAGE_INFO.getCode(), RequestAttributes.SCOPE_REQUEST);
|
||||
|
||||
if(pageObject != null){
|
||||
Paginator paginator = (Paginator)pageObject;
|
||||
|
||||
if(mav == null) {
|
||||
request.setAttribute(PagingConstants.Session.PAGE_INFO.getCode(), getPageInfoMap(paginator));
|
||||
return;
|
||||
|
||||
}else{
|
||||
mav.addObject(PagingConstants.Session.PAGE_INFO.getCode(), getPageInfoMap(paginator));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse httpServletResponse, Object o, Exception e)
|
||||
throws Exception {
|
||||
}
|
||||
|
||||
private Map<String,Object> getPageInfoMap(Paginator paginator){
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
|
||||
map.put("totalCount", paginator.getTotalCount());
|
||||
map.put("totalPages", paginator.getTotalPages());
|
||||
map.put("page", paginator.getPage());
|
||||
map.put("limit", paginator.getLimit());
|
||||
// Query Data : Paging 정보만 set 하면 되므로 필요 없다
|
||||
//map.put(FwConstants.DEFAULT_RESPONSE_BODY_DATA_NAME, new ArrayList<PageList>(pageList));
|
||||
map.put("startRow", paginator.getStartRow());
|
||||
map.put("endRow", paginator.getEndRow());
|
||||
map.put("offset", paginator.getOffset());
|
||||
//map.put("slider", paginator.getSlider());
|
||||
map.put("prePage", paginator.getPrePage());
|
||||
map.put("nextPage", paginator.getNextPage());
|
||||
map.put("firstPage", paginator.isFirstPage());
|
||||
map.put("hasNextPage", paginator.isHasNextPage());
|
||||
map.put("hasPrePage", paginator.isHasPrePage());
|
||||
map.put("lastPage", paginator.isLastPage());
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2009-2012 The MyBatis Team
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.xit.core.mybatis.paging.support;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.ibatis.executor.*;
|
||||
import org.apache.ibatis.executor.parameter.*;
|
||||
import org.apache.ibatis.mapping.*;
|
||||
import org.apache.ibatis.reflection.*;
|
||||
import org.apache.ibatis.session.*;
|
||||
import org.apache.ibatis.type.*;
|
||||
|
||||
public class DefaultParameterHandler implements ParameterHandler {
|
||||
|
||||
private final TypeHandlerRegistry typeHandlerRegistry;
|
||||
|
||||
private final MappedStatement mappedStatement;
|
||||
private final Object parameterObject;
|
||||
private BoundSql boundSql;
|
||||
private Configuration configuration;
|
||||
|
||||
public DefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
|
||||
this.mappedStatement = mappedStatement;
|
||||
this.configuration = mappedStatement.getConfiguration();
|
||||
this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
|
||||
this.parameterObject = parameterObject;
|
||||
this.boundSql = boundSql;
|
||||
}
|
||||
|
||||
public Object getParameterObject() {
|
||||
return parameterObject;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void setParameters(PreparedStatement ps) throws SQLException {
|
||||
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
|
||||
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
|
||||
if (parameterMappings != null) {
|
||||
MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject);
|
||||
for (int i = 0; i < parameterMappings.size(); i++) {
|
||||
ParameterMapping parameterMapping = parameterMappings.get(i);
|
||||
if (parameterMapping.getMode() != ParameterMode.OUT) {
|
||||
Object value;
|
||||
String propertyName = parameterMapping.getProperty();
|
||||
if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
|
||||
value = boundSql.getAdditionalParameter(propertyName);
|
||||
} else if (parameterObject == null) {
|
||||
value = null;
|
||||
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
|
||||
value = parameterObject;
|
||||
} else {
|
||||
value = metaObject == null ? null : metaObject.getValue(propertyName);
|
||||
}
|
||||
TypeHandler typeHandler = parameterMapping.getTypeHandler();
|
||||
if (typeHandler == null) {
|
||||
throw new ExecutorException(
|
||||
"There was no TypeHandler found for parameter "
|
||||
+ propertyName + " of statement "
|
||||
+ mappedStatement.getId());
|
||||
}
|
||||
JdbcType jdbcType = parameterMapping.getJdbcType();
|
||||
if (value == null && jdbcType == null)
|
||||
jdbcType = configuration.getJdbcTypeForNull();
|
||||
typeHandler.setParameter(ps, i + 1, value, jdbcType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,408 @@
|
||||
package com.xit.core.mybatis.paging.support;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.Map.*;
|
||||
|
||||
import org.apache.commons.lang3.*;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* used :
|
||||
* public class ConnectionUtils {
|
||||
* static Properties properties = new Properties();
|
||||
* // ... do load properties
|
||||
*
|
||||
* // delegate to properties
|
||||
* static PropertiesHelper props = new PropertiesHelper(properties);
|
||||
* public static Connection getConnection() {
|
||||
* // use getRequiredProperty()
|
||||
* DriverManager.getConnection(props.getRequiredString("jdbc.url"));
|
||||
* }
|
||||
* }
|
||||
* new PropertiesHelper(properties,PropertiesHelper.SYSTEM_PROPERTIES_MODE_OVERRIDE)
|
||||
* </pre>
|
||||
*/
|
||||
public class PropertiesHelper {
|
||||
/** Never check system properties. */
|
||||
public static final int SYSTEM_PROPERTIES_MODE_NEVER = 0;
|
||||
|
||||
/**
|
||||
* Check system properties if not resolvable in the specified properties.
|
||||
* This is the default.
|
||||
*/
|
||||
public static final int SYSTEM_PROPERTIES_MODE_FALLBACK = 1;
|
||||
|
||||
/**
|
||||
* Check system properties first, before trying the specified properties.
|
||||
* This allows system properties to override any other property source.
|
||||
*/
|
||||
public static final int SYSTEM_PROPERTIES_MODE_OVERRIDE = 2;
|
||||
|
||||
private int systemPropertiesMode = SYSTEM_PROPERTIES_MODE_NEVER;
|
||||
private Properties p;
|
||||
|
||||
public PropertiesHelper(Properties p) {
|
||||
setProperties(p);
|
||||
}
|
||||
|
||||
public PropertiesHelper(Properties p, int systemPropertiesMode) {
|
||||
setProperties(p);
|
||||
if(systemPropertiesMode != SYSTEM_PROPERTIES_MODE_NEVER && systemPropertiesMode != SYSTEM_PROPERTIES_MODE_FALLBACK && systemPropertiesMode != SYSTEM_PROPERTIES_MODE_OVERRIDE) {
|
||||
throw new IllegalArgumentException("error systemPropertiesMode mode:"+systemPropertiesMode);
|
||||
}
|
||||
this.systemPropertiesMode = systemPropertiesMode;
|
||||
}
|
||||
|
||||
public Properties getProperties() {
|
||||
return p;
|
||||
}
|
||||
|
||||
public void setProperties(Properties props) {
|
||||
if(props == null) throw new IllegalArgumentException("properties must be not null");
|
||||
this.p = props;
|
||||
}
|
||||
|
||||
public String getRequiredString(String key) {
|
||||
String value = getProperty(key);
|
||||
if(isBlankString(value)) {
|
||||
throw new IllegalStateException("required property is blank by key="+key);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getNullIfBlank(String key) {
|
||||
String value = getProperty(key);
|
||||
if(isBlankString(value)) {
|
||||
return null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getNullIfEmpty(String key) {
|
||||
String value = getProperty(key);
|
||||
if(StringUtils.isEmpty(value)) {
|
||||
return null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* System.getProperty(key) System.getenv(key)
|
||||
* @param key key
|
||||
* @return String
|
||||
*/
|
||||
public String getAndTryFromSystem(String key) {
|
||||
String value = getProperty(key);
|
||||
if(isBlankString(value)) {
|
||||
value = getSystemProperty(key);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private String getSystemProperty(String key) {
|
||||
String value;
|
||||
value = System.getProperty(key);
|
||||
if(isBlankString(value)) {
|
||||
value = System.getenv(key);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public Integer getInteger(String key) {
|
||||
String v = getProperty(key);
|
||||
if(v == null){
|
||||
return null;
|
||||
}
|
||||
return Integer.parseInt(v);
|
||||
}
|
||||
|
||||
public int getInt(String key,int defaultValue) {
|
||||
if(getProperty(key) == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Integer.parseInt(getRequiredString(key));
|
||||
}
|
||||
|
||||
public int getRequiredInt(String key) {
|
||||
return Integer.parseInt(getRequiredString(key));
|
||||
}
|
||||
|
||||
public Long getLong(String key) {
|
||||
if(getProperty(key) == null) {
|
||||
return null;
|
||||
}
|
||||
return Long.parseLong(getRequiredString(key));
|
||||
}
|
||||
|
||||
public long getLong(String key,long defaultValue) {
|
||||
if(getProperty(key) == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Long.parseLong(getRequiredString(key));
|
||||
}
|
||||
|
||||
public Long getRequiredLong(String key) {
|
||||
return Long.parseLong(getRequiredString(key));
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String key) {
|
||||
if(getProperty(key) == null) {
|
||||
return null;
|
||||
}
|
||||
return Boolean.parseBoolean(getRequiredString(key));
|
||||
}
|
||||
|
||||
public boolean getBoolean(String key,boolean defaultValue) {
|
||||
if(getProperty(key) == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Boolean.parseBoolean(getRequiredString(key));
|
||||
}
|
||||
|
||||
public boolean getRequiredBoolean(String key) {
|
||||
return Boolean.parseBoolean(getRequiredString(key));
|
||||
}
|
||||
|
||||
public Float getFloat(String key) {
|
||||
if(getProperty(key) == null) {
|
||||
return null;
|
||||
}
|
||||
return Float.parseFloat(getRequiredString(key));
|
||||
}
|
||||
|
||||
public float getFloat(String key,float defaultValue) {
|
||||
if(getProperty(key) == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Float.parseFloat(getRequiredString(key));
|
||||
}
|
||||
|
||||
public Float getRequiredFloat(String key) {
|
||||
return Float.parseFloat(getRequiredString(key));
|
||||
}
|
||||
|
||||
public Double getDouble(String key) {
|
||||
if(getProperty(key) == null) {
|
||||
return null;
|
||||
}
|
||||
return Double.parseDouble(getRequiredString(key));
|
||||
}
|
||||
|
||||
public double getDouble(String key,double defaultValue) {
|
||||
if(getProperty(key) == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return Double.parseDouble(getRequiredString(key));
|
||||
}
|
||||
|
||||
public Double getRequiredDouble(String key) {
|
||||
return Double.parseDouble(getRequiredString(key));
|
||||
}
|
||||
|
||||
//---------- setProperty(String key,int value) ... start ---------------//
|
||||
public Object setProperty(String key,int value) {
|
||||
return setProperty(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Object setProperty(String key,long value) {
|
||||
return setProperty(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Object setProperty(String key,float value) {
|
||||
return setProperty(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Object setProperty(String key,double value) {
|
||||
return setProperty(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Object setProperty(String key,boolean value) {
|
||||
return setProperty(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public String[] getStringArray(String key) {
|
||||
String v = getProperty(key);
|
||||
if(v == null) {
|
||||
return new String[0];
|
||||
}else {
|
||||
return tokenizeToStringArray(v, ", \t\n\r\f");
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getIntArray(String key) {
|
||||
return toIntArray(getStringArray(key));
|
||||
}
|
||||
|
||||
public Properties getStartsWithProperties(String prefix) {
|
||||
if(prefix == null) throw new IllegalArgumentException("'prefix' must be not null");
|
||||
|
||||
Properties props = getProperties();
|
||||
Properties result = new Properties();
|
||||
for(Entry<Object, Object> entry : props.entrySet()) {
|
||||
String key = (String)entry.getKey();
|
||||
if(key != null && key.startsWith(prefix)) {
|
||||
result.put(key.substring(prefix.length()), entry.getValue());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//--------- delegate method start ---//
|
||||
public String getProperty(String key, String defaultValue) {
|
||||
String value = getProperty(key);
|
||||
if(isBlankString(value)) {
|
||||
return defaultValue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getProperty(String key) {
|
||||
String propVal = null;
|
||||
if (systemPropertiesMode == SYSTEM_PROPERTIES_MODE_OVERRIDE) {
|
||||
propVal = getSystemProperty(key);
|
||||
}
|
||||
if (propVal == null) {
|
||||
propVal = p.getProperty(key);
|
||||
}
|
||||
if (propVal == null && systemPropertiesMode == SYSTEM_PROPERTIES_MODE_FALLBACK) {
|
||||
propVal = getSystemProperty(key);
|
||||
}
|
||||
return propVal;
|
||||
}
|
||||
|
||||
public Object setProperty(String key,String value) {
|
||||
return p.setProperty(key, value);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
p.clear();
|
||||
}
|
||||
|
||||
public Set<Entry<Object, Object>> entrySet() {
|
||||
return p.entrySet();
|
||||
}
|
||||
|
||||
public Enumeration<?> propertyNames() {
|
||||
return p.propertyNames();
|
||||
}
|
||||
|
||||
public boolean contains(Object value) {
|
||||
return p.contains(value);
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
return p.containsKey(key);
|
||||
}
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
return p.containsValue(value);
|
||||
}
|
||||
|
||||
public Enumeration<Object> elements() {
|
||||
return p.elements();
|
||||
}
|
||||
|
||||
public Object get(Object key) {
|
||||
return p.get(key);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return p.isEmpty();
|
||||
}
|
||||
|
||||
public Enumeration<Object> keys() {
|
||||
return p.keys();
|
||||
}
|
||||
|
||||
public Set<Object> keySet() {
|
||||
return p.keySet();
|
||||
}
|
||||
|
||||
public void list(PrintStream out) {
|
||||
p.list(out);
|
||||
}
|
||||
|
||||
public void list(PrintWriter out) {
|
||||
p.list(out);
|
||||
}
|
||||
|
||||
public void load(InputStream inStream) throws IOException {
|
||||
p.load(inStream);
|
||||
}
|
||||
|
||||
public void loadFromXML(InputStream in) throws IOException,
|
||||
InvalidPropertiesFormatException {
|
||||
p.loadFromXML(in);
|
||||
}
|
||||
|
||||
public Object put(Object key, Object value) {
|
||||
return p.put(key, value);
|
||||
}
|
||||
|
||||
public void putAll(Map<? extends Object, ? extends Object> t) {
|
||||
p.putAll(t);
|
||||
}
|
||||
|
||||
public Object remove(Object key) {
|
||||
return p.remove(key);
|
||||
}
|
||||
|
||||
/**@deprecated
|
||||
* @param out out
|
||||
* @param comments comments
|
||||
*/
|
||||
@Deprecated
|
||||
public void save(OutputStream out, String comments) {
|
||||
p.save(out, comments);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return p.size();
|
||||
}
|
||||
|
||||
public void store(OutputStream out, String comments) throws IOException {
|
||||
p.store(out, comments);
|
||||
}
|
||||
|
||||
public void storeToXML(OutputStream os, String comment, String encoding)
|
||||
throws IOException {
|
||||
p.storeToXML(os, comment, encoding);
|
||||
}
|
||||
|
||||
public void storeToXML(OutputStream os, String comment) throws IOException {
|
||||
p.storeToXML(os, comment);
|
||||
}
|
||||
|
||||
public Collection<Object> values() {
|
||||
return p.values();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return p.toString();
|
||||
}
|
||||
|
||||
private static boolean isBlankString(String value) {
|
||||
return Objects.isNull(value) || Objects.equals(StringUtils.EMPTY, value.trim());
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private static String[] tokenizeToStringArray(String str, String sep) {
|
||||
StringTokenizer st = new StringTokenizer(str, sep);
|
||||
List result = new ArrayList();
|
||||
|
||||
while(st.hasMoreElements()) {
|
||||
Object o = st.nextElement();
|
||||
result.add(o);
|
||||
}
|
||||
return (String[])result.toArray(new String[result.size()]);
|
||||
}
|
||||
|
||||
private static int[] toIntArray(String[] array) {
|
||||
int[] result = new int[array.length];
|
||||
for(int i = 0; i < array.length; i++) {
|
||||
result[i] = Integer.parseInt(array[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2013, Poplar Yfyang 杨友峰 (poplar1123@gmail.com).
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.xit.core.mybatis.paging.support;
|
||||
|
||||
import java.sql.*;
|
||||
|
||||
import org.apache.ibatis.mapping.*;
|
||||
import org.slf4j.*;
|
||||
|
||||
import com.xit.core.mybatis.paging.dialect.*;
|
||||
|
||||
public class SQLHelp {
|
||||
|
||||
/**
|
||||
* query record total count
|
||||
*
|
||||
* @param mappedStatement mapped
|
||||
* @param parameterObject parameter
|
||||
* @param boundSql boundSql
|
||||
* @param dialect database dialect
|
||||
* @return int
|
||||
* @throws SQLException SQLException
|
||||
*/
|
||||
public static int getCount(final MappedStatement mappedStatement, final Object parameterObject, final BoundSql boundSql, Dialect dialect) throws SQLException {
|
||||
final String count_sql = dialect.getCountSQL();
|
||||
|
||||
Connection connection = null;
|
||||
PreparedStatement countStmt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
connection = mappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection();
|
||||
countStmt = connection.prepareStatement(count_sql);
|
||||
DefaultParameterHandler handler = new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
|
||||
handler.setParameters(countStmt);
|
||||
rs = countStmt.executeQuery();
|
||||
int count = 0;
|
||||
|
||||
if (rs.next()) count = rs.getInt(1);
|
||||
// log.debug("Total count:{}, SQL:{}, parameters:{}", count, count_sql, parameterObject);
|
||||
return count;
|
||||
|
||||
} finally {
|
||||
try {
|
||||
if (rs != null) rs.close();
|
||||
} finally {
|
||||
try {
|
||||
if (countStmt != null) countStmt.close();
|
||||
} finally {
|
||||
if (connection != null && !connection.isClosed()) connection.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
package com.xit.core.mybatis.paging.util;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.lang3.*;
|
||||
import org.apache.ibatis.session.*;
|
||||
|
||||
import com.xit.core.mybatis.paging.domain.*;
|
||||
|
||||
import egovframework.com.cmm.*;
|
||||
|
||||
public class MybatisUtils {
|
||||
public static <T> RowBounds getPagingInfo(Map<String,Object> map){
|
||||
if(ObjectUtils.isEmpty(map)){
|
||||
return new PageBounds(1, 10);
|
||||
}
|
||||
int page = ObjectUtils.isEmpty(map.get("page")) || Integer.parseInt(String.valueOf(map.get("page"))) < 0? 1: Integer.parseInt(String.valueOf(map.get("page")));
|
||||
int limit = ObjectUtils.isEmpty(map.get("perPage")) || Integer.parseInt(String.valueOf(map.get("perPage"))) < 0? 20: Integer.parseInt(String.valueOf(map.get("perPage")));
|
||||
// 정렬필드명.direction,정렬필드명.direction,... 형태(정렬필드,정렬필드.desc)
|
||||
String sort = ObjectUtils.isEmpty(map.get("sidx"))? "": String.valueOf(map.get("sidx"));
|
||||
return new PageBounds(page, limit , Order.formString(sort));
|
||||
}
|
||||
|
||||
public static <T> RowBounds getPagingInfo(Object cls){
|
||||
int page = 0;
|
||||
int limit = 0;
|
||||
|
||||
if(ObjectUtils.isEmpty(cls)){
|
||||
return new PageBounds(1, 10);
|
||||
}
|
||||
try {
|
||||
Method pageMethod = cls.getClass().getMethod("getPage");
|
||||
if(ObjectUtils.isNotEmpty(pageMethod)) page = (Integer)pageMethod.invoke(cls, null);
|
||||
|
||||
Method limitMethod = cls.getClass().getMethod("getPerPage");
|
||||
if(ObjectUtils.isNotEmpty(limitMethod)) limit = (Integer)limitMethod.invoke(cls, null);
|
||||
} catch (IllegalAccessException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
page = page == 0? 1: page;
|
||||
limit = limit == 0? 20: limit;
|
||||
// 정렬필드명.direction,정렬필드명.direction,... 형태(정렬필드,정렬필드.desc)
|
||||
//String sort = Checks.isEmpty(map.get("sidx"))? "": String.valueOf(map.get("sidx"));
|
||||
//return new RowBounds(page == 1? 1: (page-1)*limit, limit);
|
||||
return new PageBounds(page, limit);
|
||||
}
|
||||
|
||||
// 전자정부 프레임워크 파라메터 적용 추가
|
||||
public static <T> RowBounds getPagingInfo(ComDefaultVO comDefaultVO) {
|
||||
return new PageBounds(comDefaultVO.getPageIndex(), comDefaultVO.getRecordCountPerPage());
|
||||
}
|
||||
|
||||
public static RowBounds getPagingInfo(final int page, final int limit){
|
||||
return new PageBounds(page, limit);
|
||||
}
|
||||
|
||||
public static RowBounds getPagingInfo(int page, int row, String sort){
|
||||
|
||||
return new PageBounds(page, row, Order.formString(sort));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package com.xit.core.mybatis.paging.util;
|
||||
|
||||
import org.egovframe.rte.ptl.mvc.tags.ui.pagination.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @업무그룹명: paging 처리를 위한 VO
|
||||
* @설명: Grid 컴포넌트 및 기존 코드를 병행 활용하기 위해 PaginationInfo 클래스를 상속 받아 사용한ㄷ.
|
||||
* @최초작성일: 2020. 5. 26. 오전 9:11:58
|
||||
* @최초작성자: 임종욱
|
||||
* @author (주)엑스아이티 개발팀
|
||||
* @since 2002. 2. 2.
|
||||
* @version 1.0 Copyright(c) XIT All rights reserved.
|
||||
*/
|
||||
public class XitPaginationInfo extends PaginationInfo{
|
||||
|
||||
/* *************************
|
||||
* tui Grid Paging 필드
|
||||
************************* */
|
||||
/** 현재 페이지 */
|
||||
private int page = -1;
|
||||
/** 모든 로우들의 개수(=조회 총 건수) */
|
||||
private int totalCount = -1;
|
||||
/* *************************
|
||||
* //tui Grid Paging 필드
|
||||
************************* */
|
||||
|
||||
|
||||
/** [tui Grid] 현재 페이지를 반환 한다. */
|
||||
public int getPage() {
|
||||
return page;
|
||||
}
|
||||
/** [tui Grid] 현재 페이지를 설정 한다. */
|
||||
public void setPage(int page) {
|
||||
this.page = page;
|
||||
super.setCurrentPageNo(page);
|
||||
}
|
||||
/** [tui Grid] 조회 총 건수를 설정 한다. */
|
||||
public int getTotalCount() {
|
||||
return totalCount;
|
||||
}
|
||||
/** [tui Grid] 조회 총 건수를 반환 한다. */
|
||||
public void setTotalCount(int totalCount) {
|
||||
this.totalCount = totalCount;
|
||||
super.setTotalRecordCount(totalCount);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,81 @@
|
||||
package com.xit.core.mybatis.paging.util;
|
||||
|
||||
import javax.servlet.*;
|
||||
|
||||
import org.egovframe.rte.ptl.mvc.tags.ui.pagination.*;
|
||||
import org.springframework.web.context.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @업무그룹명: Page Rendedrer 클래스
|
||||
* @설명:
|
||||
* @최초작성일: 2020. 4. 28. 오후 1:10:13
|
||||
* @최초작성자: 임종욱
|
||||
* @author (주)엑스아이티 개발팀
|
||||
* @since 2002. 2. 2.
|
||||
* @version 1.0 Copyright(c) XIT All rights reserved.
|
||||
*/
|
||||
public class XitPaginationRenderer extends AbstractPaginationRenderer implements ServletContextAware{
|
||||
|
||||
private ServletContext servletContext;
|
||||
|
||||
String type ;
|
||||
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public XitPaginationRenderer() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
public void initVariables(){
|
||||
firstPageLabel = "<a href=\"#none\" class=\"btn prevAll\" onclick=\"{0}({1}); return false;\"><span class=\"blind\">처음페이지</span></a>";
|
||||
previousPageLabel = "<a href=\"#none\" class=\"btn prev\" onclick=\"{0}({1}); return false;\"><span class=\"blind\">이전페이지</span></a>";
|
||||
currentPageLabel = "<strong class=\"on\">{0}</strong>";
|
||||
otherPageLabel = "<a href=\"#none\" onclick=\"{0}({1}); return false;\">{2}</a>";
|
||||
nextPageLabel = "<a href=\"#none\" class=\"btn next\" onclick=\"{0}({1}); return false;\"><span class=\"blind\">다음페이지</span></a>";
|
||||
lastPageLabel = "<a href=\"#none\" class=\"btn nextAll\" onclick=\"{0}({1}); return false;\"><span class=\"blind\">마지막페이지</span></a>";
|
||||
|
||||
/* <a href=\"#none\" class=\"btn prevAll\" onclick=\"{0}({1}); return false;\"><span class=\"blind\">처음페이지</span></a>
|
||||
<a href=\"#none\" class=\"btn prev\" onclick=\"{0}({1}); return false;\"><span class=\"blind\">이전페이지</span></a>
|
||||
<strong class=\"on\">{0}</strong>
|
||||
<a href=\"#none\" onclick=\"{0}({1}); return false;\">{2}</a>
|
||||
<a href=\"#none\" class=\"btn next\" onclick=\"{0}({1}); return false;\"><span class=\"blind\">다음페이지</span></a>
|
||||
<a href=\"#none\" class=\"btn nextAll\" onclick=\"{0}({1}); return false;\"><span class=\"blind\">마지막페이지</span></a>
|
||||
*/
|
||||
/*//이미지 방식
|
||||
firstPageLabel = "<a class=\"btn prevAll\" href=\"#\" onclick=\"{0}({1}); return false;\">" +
|
||||
"<img src='" + strWebDir + "prevAll.png' border='0' alt='첫페이지'/></a> ";
|
||||
previousPageLabel = "<a class=\"btn prev\" href=\"#\" onclick=\"{0}({1}); return false;\">" +
|
||||
"<img src='" + strWebDir + "prev.png' border='0' alt='이전페이지'/></a> ";
|
||||
currentPageLabel = "<strong class='on'>{0}</strong> ";
|
||||
otherPageLabel = "<a href=\"#\" onclick=\"{0}({1}); return false;\">{2}</a> ";
|
||||
nextPageLabel = "<a class=\"btn next\" href=\"#\" onclick=\"{0}({1}); return false;\">" +
|
||||
"<img src='" + strWebDir + "next.png' border='0' alt='다음페이지'/></a> ";
|
||||
lastPageLabel = "<a class=\"btn nextAll\" href=\"#\" onclick=\"{0}({1}); return false;\">" +
|
||||
"<img src='" + strWebDir + "nextAll.png' border='0' alt='마지막페이지'/></a> ";
|
||||
|
||||
*/
|
||||
/*
|
||||
firstPageLabel = "<a href=\"?pageIndex={1}\" onclick=\"{0}({1});return false; \"><img src=\"" + servletContext.getContextPath() + "/resources/image/fims/framework/egovframework/com/cmm/icon/icon_prevend.gif\" alt=\"처음\" border=\"0\"/></a> ";
|
||||
previousPageLabel = "<a href=\"?pageIndex={1}\" onclick=\"{0}({1});return false; \"><img src=\"" + servletContext.getContextPath() + "/resources/image/fims/framework/egovframework/com/cmm/icon/icon_prev.gif\" alt=\"이전\" border=\"0\"/></a> ";
|
||||
currentPageLabel = "<strong>{0}</strong> ";
|
||||
otherPageLabel = "<a href=\"?pageIndex={1}\" onclick=\"{0}({1});return false; \">{2}</a> ";
|
||||
nextPageLabel = "<a href=\"?pageIndex={1}\" onclick=\"{0}({1});return false; \"><img src=\"" + servletContext.getContextPath() + "/resources/image/fims/framework/egovframework/com/cmm/icon/icon_next.gif\" alt=\"다음\" border=\"0\"/></a> ";
|
||||
lastPageLabel = "<a href=\"?pageIndex={1}\" onclick=\"{0}({1});return false; \"><img src=\"" + servletContext.getContextPath() + "/resources/image/fims/framework/egovframework/com/cmm/icon/icon_nextend.gif\" alt=\"마지막\" border=\"0\"/></a> ";
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setServletContext(ServletContext servletContext) {
|
||||
this.servletContext = servletContext;
|
||||
initVariables();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue