private void pagination(Invocation invocation, StatementHandler target) throws SQLException { final MetaObject metaStatementHandler = getMetaObject(target); final BoundSql boundSql = target.getBoundSql(); Page<?> page = PAGE_THREAD_LOCAL.get(); if (page == null) { page = findPageParameter(boundSql.getParameterObject()); } // 如果传入的参数中有分页对象且sql语句中有select,才做分页处理 String sql = boundSql.getSql().toLowerCase(); if (sql.startsWith("select") && page != null) { // 采用物理分页后,就不需要mybatis的内存分页了,所以重置下面的两个参数 metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET); metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT); // 设置分页对象里的总记录数和总页数 Connection connection = (Connection) invocation.getArgs()[0]; MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement"); if (page.isCountTotal()) { int recordsTotal = getTotalCount(sql, connection, mappedStatement, boundSql); page.setTotalNum(recordsTotal); } // 最后重写sql String pageSql = buildPageSql(sql, page); metaStatementHandler.setValue("delegate.boundSql.sql", pageSql); } }
private boolean applyNestedResultMappings( ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String parentPrefix, CacheKey parentRowKey, boolean newObject) { boolean foundValues = false; for (ResultMapping resultMapping : resultMap.getPropertyResultMappings()) { final String nestedResultMapId = resultMapping.getNestedResultMapId(); if (nestedResultMapId != null && resultMapping.getResultSet() == null) { try { final String columnPrefix = getColumnPrefix(parentPrefix, resultMapping); final ResultMap nestedResultMap = getNestedResultMap(rsw.getResultSet(), nestedResultMapId, columnPrefix); CacheKey rowKey = null; Object ancestorObject = null; if (ancestorColumnPrefix.containsKey(nestedResultMapId)) { rowKey = createRowKey(nestedResultMap, rsw, ancestorColumnPrefix.get(nestedResultMapId)); ancestorObject = ancestorObjects.get(rowKey); } if (ancestorObject != null) { if (newObject) metaObject.setValue(resultMapping.getProperty(), ancestorObject); } else { rowKey = createRowKey(nestedResultMap, rsw, columnPrefix); final CacheKey combinedKey = combineKeys(rowKey, parentRowKey); Object rowValue = nestedResultObjects.get(combinedKey); boolean knownValue = (rowValue != null); final Object collectionProperty = instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject); if (anyNotNullColumnHasValue(resultMapping, columnPrefix, rsw.getResultSet())) { rowValue = getRowValue(rsw, nestedResultMap, combinedKey, rowKey, columnPrefix, rowValue); if (rowValue != null && !knownValue) { if (collectionProperty != null) { final MetaObject targetMetaObject = configuration.newMetaObject(collectionProperty); targetMetaObject.add(rowValue); } else { metaObject.setValue(resultMapping.getProperty(), rowValue); } foundValues = true; } } } } catch (SQLException e) { throw new ExecutorException( "Error getting nested result map values for '" + resultMapping.getProperty() + "'. Cause: " + e, e); } } } return foundValues; }
private void setCacheProperties(Cache cache) { if (properties != null) { MetaObject metaCache = SystemMetaObject.forObject(cache); for (Map.Entry<Object, Object> entry : properties.entrySet()) { String name = (String) entry.getKey(); String value = (String) entry.getValue(); if (metaCache.hasSetter(name)) { Class<?> type = metaCache.getSetterType(name); if (String.class == type) { metaCache.setValue(name, value); } else if (int.class == type || Integer.class == type) { metaCache.setValue(name, Integer.valueOf(value)); } else if (long.class == type || Long.class == type) { metaCache.setValue(name, Long.valueOf(value)); } else if (short.class == type || Short.class == type) { metaCache.setValue(name, Short.valueOf(value)); } else if (byte.class == type || Byte.class == type) { metaCache.setValue(name, Byte.valueOf(value)); } else if (float.class == type || Float.class == type) { metaCache.setValue(name, Float.valueOf(value)); } else if (boolean.class == type || Boolean.class == type) { metaCache.setValue(name, Boolean.valueOf(value)); } else if (double.class == type || Double.class == type) { metaCache.setValue(name, Double.valueOf(value)); } else { throw new CacheException( "Unsupported property type for cache: '" + name + "' of type " + type); } } } } }
private void processGeneratedKeys(Executor executor, MappedStatement ms, Object parameter) { try { if (parameter != null && keyStatement != null && keyStatement.getKeyProperties() != null) { String keyProperty = keyStatement.getKeyProperties()[0]; // just one key property is supported final Configuration configuration = ms.getConfiguration(); final MetaObject metaParam = configuration.newMetaObject(parameter); if (keyProperty != null && metaParam.hasSetter(keyProperty)) { // Do not close keyExecutor. // The transaction will be closed by parent executor. Executor keyExecutor = configuration.newExecutor(executor.getTransaction(), ExecutorType.SIMPLE); List<Object> values = keyExecutor.query( keyStatement, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER); if (values.size() == 0) { throw new ExecutorException("SelectKey returned no data."); } else if (values.size() > 1) { throw new ExecutorException("SelectKey returned more than one value."); } else { metaParam.setValue(keyProperty, values.get(0)); } } } } catch (ExecutorException e) { throw e; } catch (Exception e) { throw new ExecutorException( "Error selecting key or setting result to parameter object. Cause: " + e, e); } }
private Object instantiateCollectionPropertyIfAppropriate( ResultMapping resultMapping, MetaObject metaObject) { final String propertyName = resultMapping.getProperty(); Object propertyValue = metaObject.getValue(propertyName); if (propertyValue == null) { Class<?> type = resultMapping.getJavaType(); if (type == null) { type = metaObject.getSetterType(propertyName); } try { if (objectFactory.isCollection(type)) { propertyValue = objectFactory.create(type); metaObject.setValue(propertyName, propertyValue); return propertyValue; } } catch (Exception e) { throw new ExecutorException( "Error instantiating collection property for result '" + resultMapping.getProperty() + "'. Cause: " + e, e); } } else if (objectFactory.isCollection(propertyValue.getClass())) { return propertyValue; } return null; }
private boolean applyAutomaticMappings( ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException { final List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix); boolean foundValues = false; for (String columnName : unmappedColumnNames) { String propertyName = columnName; if (columnPrefix != null && columnPrefix.length() > 0) { // When columnPrefix is specified, // ignore columns without the prefix. if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) { propertyName = columnName.substring(columnPrefix.length()); } else { continue; } } final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase()); if (property != null && metaObject.hasSetter(property)) { final Class<?> propertyType = metaObject.getSetterType(property); if (typeHandlerRegistry.hasTypeHandler(propertyType)) { final TypeHandler<?> typeHandler = rsw.getTypeHandler(propertyType, columnName); final Object value = typeHandler.getResult(rsw.getResultSet(), columnName); if (value != null || configuration.isCallSettersOnNulls()) { // issue #377, call setter on nulls if (value != null || !propertyType.isPrimitive()) { metaObject.setValue(property, value); } foundValues = true; } } } } return foundValues; }
@Test public void shouldGetAndSetNestedProperty() { RichType rich = new RichType(); MetaObject meta = SystemMetaObject.forObject(rich); meta.setValue("richType.richProperty", "foo"); assertEquals("foo", meta.getValue("richType.richProperty")); }
private boolean applyPropertyMappings( ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException { final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix); boolean foundValues = false; final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings(); for (ResultMapping propertyMapping : propertyMappings) { final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix); if (propertyMapping.isCompositeResult() || (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH))) || propertyMapping.getResultSet() != null) { Object value = getPropertyMappingValue( rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix); final String property = propertyMapping.getProperty(); // issue #541 make property optional if (value != NO_VALUE && property != null && (value != null || configuration.isCallSettersOnNulls())) { // issue #377, call setter on nulls if (value != null || !metaObject.getSetterType(property).isPrimitive()) { metaObject.setValue(property, value); } foundValues = true; } } } return foundValues; }
@Test public void shouldGetAndSetMapPair() { RichType rich = new RichType(); MetaObject meta = SystemMetaObject.forObject(rich); meta.setValue("richMap.key", "foo"); assertEquals("foo", meta.getValue("richMap.key")); }
@Test public void shouldGetAndSetNestedMapPairUsingArraySyntax() { RichType rich = new RichType(); MetaObject meta = SystemMetaObject.forObject(rich); meta.setValue("richType.richMap[key]", "foo"); assertEquals("foo", meta.getValue("richType.richMap[key]")); }
public Object intercept(Invocation invocation) throws Throwable { StatementHandler handler = (StatementHandler) invocation.getTarget(); MetaObject metaObject = MetaObject.forObject(handler); Page page = pageByMetaObject(metaObject); if (page == null || (page.getPageCount() == 0 && page.getPageSize() == 0)) return invocation.proceed(); Configuration configuration = (Configuration) metaObject.getValue("delegate.configuration"); BoundSql orgBoundSql = (BoundSql) metaObject.getValue("delegate.boundSql"); if (page.getCount() == 0) { MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement"); page.setCount( totalCount( (Connection) invocation.getArgs()[0], orgBoundSql, configuration, mappedStatement)); } metaObject.setValue( "delegate.boundSql.sql", searchDialectByDbTypeEnum(configuration, page) .spellPageSql(orgBoundSql.getSql(), page.getOffset(), page.getLimit())); logger.debug("pagination sql : {}", handler.getBoundSql().getSql()); return invocation.proceed(); }
@Test public void shouldSetAndGetSelfListItem() { RichType rich = new RichType(); MetaObject meta = SystemMetaObject.forObject(rich); meta.setValue("richList[0]", "foo"); assertEquals("foo", meta.getValue("richList[0]")); }
@Test public void shouldDemonstrateDeeplyNestedMapProperties() { HashMap<String, String> map = new HashMap<String, String>(); MetaObject metaMap = SystemMetaObject.forObject(map); assertTrue(metaMap.hasSetter("id")); assertTrue(metaMap.hasSetter("name.first")); assertTrue(metaMap.hasSetter("address.street")); assertFalse(metaMap.hasGetter("id")); assertFalse(metaMap.hasGetter("name.first")); assertFalse(metaMap.hasGetter("address.street")); metaMap.setValue("id", "100"); metaMap.setValue("name.first", "Clinton"); metaMap.setValue("name.last", "Begin"); metaMap.setValue("address.street", "1 Some Street"); metaMap.setValue("address.city", "This City"); metaMap.setValue("address.province", "A Province"); metaMap.setValue("address.postal_code", "1A3 4B6"); assertTrue(metaMap.hasGetter("id")); assertTrue(metaMap.hasGetter("name.first")); assertTrue(metaMap.hasGetter("address.street")); assertEquals(3, metaMap.getGetterNames().length); assertEquals(3, metaMap.getSetterNames().length); Map<String, String> name = (Map<String, String>) metaMap.getValue("name"); Map<String, String> address = (Map<String, String>) metaMap.getValue("address"); assertEquals("Clinton", name.get("first")); assertEquals("1 Some Street", address.get("street")); }
@Test public void shouldDemonstrateNullValueInMap() { HashMap<String, String> map = new HashMap<String, String>(); MetaObject metaMap = SystemMetaObject.forObject(map); assertFalse(metaMap.hasGetter("phone.home")); metaMap.setValue("phone", null); assertTrue(metaMap.hasGetter("phone")); // hasGetter returns true if the parent exists and is null. assertTrue(metaMap.hasGetter("phone.home")); assertTrue(metaMap.hasGetter("phone.home.ext")); assertNull(metaMap.getValue("phone")); assertNull(metaMap.getValue("phone.home")); assertNull(metaMap.getValue("phone.home.ext")); metaMap.setValue("phone.office", "789"); assertFalse(metaMap.hasGetter("phone.home")); assertFalse(metaMap.hasGetter("phone.home.ext")); assertEquals("789", metaMap.getValue("phone.office")); assertNotNull(metaMap.getValue("phone")); assertNull(metaMap.getValue("phone.home")); }
private void handleRefCursorOutputParameter( ResultSet rs, ParameterMapping parameterMapping, MetaObject metaParam) throws SQLException { try { final String resultMapId = parameterMapping.getResultMapId(); final ResultMap resultMap = configuration.getResultMap(resultMapId); final DefaultResultHandler resultHandler = new DefaultResultHandler(objectFactory); final ResultSetWrapper rsw = new ResultSetWrapper(rs, configuration); handleRowValues(rsw, resultMap, resultHandler, new RowBounds(), null); metaParam.setValue(parameterMapping.getProperty(), resultHandler.getResultList()); } finally { closeResultSet(rs); // issue #228 (close resultsets) } }
@Override public Object intercept(Invocation invocation) throws Throwable { StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); ParameterHandler parameterHandler = statementHandler.getParameterHandler(); BoundSql boundSql = statementHandler.getBoundSql(); MetaObject metaStatementHandler = MetaObject.forObject( statementHandler, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY); RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds"); // 没有分页参数 if (rowBounds == null || rowBounds == RowBounds.DEFAULT) { return invocation.proceed(); } Configuration configuration = (Configuration) metaStatementHandler.getValue("delegate.configuration"); Dialect dialect = DialectFactory.buildDialect(configuration); String originalSql = (String) metaStatementHandler.getValue("delegate.boundSql.sql"); // 获取总记录数 Page<?> page = (Page<?>) rowBounds; String countSql = dialect.getCountString(originalSql); Connection connection = (Connection) invocation.getArgs()[0]; int total = getTotal(parameterHandler, connection, countSql); page.setTotalCount(total); // 设置物理分页语句 metaStatementHandler.setValue( "delegate.boundSql.sql", dialect.getLimitString(originalSql, page.getOffset(), page.getLimit())); // 屏蔽mybatis原有分页 metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET); metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT); if (logger.isDebugEnabled()) { logger.debug("分页SQL : " + boundSql.getSql()); } return invocation.proceed(); }
@Override public Object intercept(Invocation invocation) throws Throwable { FastResultSetHandler resultSetHandler = (FastResultSetHandler) invocation.getTarget(); MetaObject metaStatementHandler = MetaObject.forObject( resultSetHandler, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY); RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("rowBounds"); Object result = invocation.proceed(); if (rowBounds instanceof Page) { metaStatementHandler.setValue("rowBounds.result", result); } return result; }
private void handleLocallyCachedOutputParameters( MappedStatement ms, CacheKey key, Object parameter, BoundSql boundSql) { if (ms.getStatementType() == StatementType.CALLABLE) { final Object cachedParameter = localOutputParameterCache.getObject(key); if (cachedParameter != null && parameter != null) { final MetaObject metaCachedParameter = MetaObject.forObject(cachedParameter); final MetaObject metaParameter = MetaObject.forObject(parameter); for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) { if (parameterMapping.getMode() != ParameterMode.IN) { final String parameterName = parameterMapping.getProperty(); final Object cachedValue = metaCachedParameter.getValue(parameterName); metaParameter.setValue(parameterName, cachedValue); } } } } }
public void setValue(String name, Object value) { PropertyTokenizer prop = new PropertyTokenizer(name); if (prop.hasNext()) { org.apache.ibatis.reflection.MetaObject metaValue = metaObjectForProperty(prop.getIndexedName()); if (metaValue == SystemMetaObject.NULL_META_OBJECT) { if (value == null && prop.getChildren() != null) { return; // don't instantiate child path if value is null } else { metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory); } } metaValue.setValue(prop.getChildren(), value); } else { objectWrapper.set(prop, value); } }
private Object prepareCompositeKeyParameter( ResultSet rs, ResultMapping resultMapping, Class<?> parameterType, String columnPrefix) throws SQLException { final Object parameterObject = instantiateParameterObject(parameterType); final MetaObject metaObject = configuration.newMetaObject(parameterObject); boolean foundValues = false; for (ResultMapping innerResultMapping : resultMapping.getComposites()) { final Class<?> propType = metaObject.getSetterType(innerResultMapping.getProperty()); final TypeHandler<?> typeHandler = typeHandlerRegistry.getTypeHandler(propType); final Object propValue = typeHandler.getResult(rs, prependPrefix(innerResultMapping.getColumn(), columnPrefix)); if (propValue != null) { // issue #353 & #560 do not execute nested query if key is null metaObject.setValue(innerResultMapping.getProperty(), propValue); foundValues = true; } } return foundValues ? parameterObject : null; }
public void handleOutputParameters(CallableStatement cs) throws SQLException { final Object parameterObject = parameterHandler.getParameterObject(); final MetaObject metaParam = configuration.newMetaObject(parameterObject); final List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); for (int i = 0; i < parameterMappings.size(); i++) { final ParameterMapping parameterMapping = parameterMappings.get(i); if (parameterMapping.getMode() == ParameterMode.OUT || parameterMapping.getMode() == ParameterMode.INOUT) { if (ResultSet.class.equals(parameterMapping.getJavaType())) { handleRefCursorOutputParameter( (ResultSet) cs.getObject(i + 1), parameterMapping, metaParam); } else { final TypeHandler<?> typeHandler = parameterMapping.getTypeHandler(); metaParam.setValue(parameterMapping.getProperty(), typeHandler.getResult(cs, i + 1)); } } } }
private Cache setStandardDecorators(Cache cache) { try { MetaObject metaCache = SystemMetaObject.forObject(cache); if (size != null && metaCache.hasSetter("size")) { metaCache.setValue("size", size); } if (clearInterval != null) { cache = new ScheduledCache(cache); ((ScheduledCache) cache).setClearInterval(clearInterval); } if (readWrite) { cache = new SerializedCache(cache); } cache = new LoggingCache(cache); cache = new SynchronizedCache(cache); return cache; } catch (Exception e) { throw new CacheException("Error building standard cache decorators. Cause: " + e, e); } }
@SuppressWarnings({"rawtypes", "unchecked"}) private void autoMap(Invocation invocation, String name) throws ClassNotFoundException { final Object[] queryArgs = invocation.getArgs(); final MappedStatement ms = (MappedStatement) queryArgs[0]; final Object parameter = queryArgs[1]; String statementId = ms.getId(); MapperMeta meta = getMapperMeta(ms.getConfiguration(), statementId); if (meta.isFillEntity()) { // 将泛型类加入到参数中供CrudTemplate使用 if (parameter != null) { Map map; if (parameter instanceof Map) { map = (HashMap) parameter; map.put(CrudProvider.CLASS_KEY, meta.getEntity()); } else { map = new HashMap(); map.put(CrudProvider.PARA_KEY, parameter); map.put(CrudProvider.CLASS_KEY, meta.getEntity()); } queryArgs[1] = map; } else { queryArgs[1] = meta.getEntity(); } } if (meta.isFillResultMap()) { MetaObject metaMappedStatement = getMetaObject(ms); metaMappedStatement.setValue("resultMaps", meta.getResultMaps()); } if (name.equals("query")) { final RowBounds rowBounds = (RowBounds) queryArgs[2]; if (rowBounds == null || rowBounds == RowBounds.DEFAULT) { Page p = findPageParameter(queryArgs[1]); if (p != null) { queryArgs[2] = new RowBounds(p.getOffset(), p.getLimit()); } } } }
/** * 修改SqlSource * * @param ms * @param parser * @throws Throwable */ public static void processMappedStatement(MappedStatement ms, Parser parser) throws Throwable { SqlSource sqlSource = ms.getSqlSource(); MetaObject msObject = SystemMetaObject.forObject(ms); SqlSource tempSqlSource = sqlSource; if (sqlSource instanceof OrderBySqlSource) { tempSqlSource = ((OrderBySqlSource) tempSqlSource).getOriginal(); } SqlSource pageSqlSource; if (tempSqlSource instanceof StaticSqlSource) { pageSqlSource = new PageStaticSqlSource((StaticSqlSource) tempSqlSource, parser); } else if (tempSqlSource instanceof RawSqlSource) { pageSqlSource = new PageRawSqlSource((RawSqlSource) tempSqlSource, parser); } else if (tempSqlSource instanceof ProviderSqlSource) { pageSqlSource = new PageProviderSqlSource((ProviderSqlSource) tempSqlSource, parser); } else if (tempSqlSource instanceof DynamicSqlSource) { pageSqlSource = new PageDynamicSqlSource((DynamicSqlSource) tempSqlSource, parser); } else { throw new RuntimeException("无法处理该类型[" + sqlSource.getClass() + "]的SqlSource"); } msObject.setValue("sqlSource", pageSqlSource); // 由于count查询需要修改返回值,因此这里要创建一个Count查询的MS msCountMap.put(ms.getId(), MSUtils.newCountMappedStatement(ms)); }
public void load() { Object value = null; @SuppressWarnings("unchecked") // we suppose we get back a List List<Object> list = (List<Object>) localCache.getObject(key); Class<?> targetType = resultObject.getSetterType(property); if (targetType.isAssignableFrom(list.getClass())) { value = list; } else if (objectFactory.isCollection(targetType)) { value = objectFactory.create(targetType); MetaObject metaObject = configuration.newMetaObject(value); metaObject.addAll(list); } else if (targetType.isArray()) { Object[] array = (Object[]) Array.newInstance(targetType.getComponentType(), list.size()); value = list.toArray(array); } else { if (list != null && list.size() > 1) { throw new ExecutorException( "Statement returned more than one row, where no more than one was expected."); } else if (list != null && list.size() == 1) { value = list.get(0); } } resultObject.setValue(property, value); }
@Test public void shouldSetAndGetProperties() { MetaObject object = SystemMetaObject.forObject(new Author()); object.setValue("email", "test"); assertEquals("test", object.getValue("email")); }
@Test public void shouldSetPropertyOfNullNestedPropertyWithNull() { MetaObject richWithNull = SystemMetaObject.forObject(new RichType()); richWithNull.setValue("richType.richProperty", null); assertEquals(null, richWithNull.getValue("richType.richProperty")); }
@Override public Object intercept(Invocation invocation) throws Throwable { StatementHandler statementHandler = (StatementHandler) invocation.getTarget(); MetaObject metaStatementHandler = MetaObject.forObject( statementHandler, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_REFLECTOR_FACTORY); // 分离代理对象链(由于目标类可能被多个拦截器拦截,从而形成多次代理,通过下面的两次循环 // 可以分离出最原始的的目标类) while (metaStatementHandler.hasGetter("h")) { Object object = metaStatementHandler.getValue("h"); metaStatementHandler = MetaObject.forObject( object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_REFLECTOR_FACTORY); } // 分离最后一个代理对象的目标类 while (metaStatementHandler.hasGetter("target")) { Object object = metaStatementHandler.getValue("target"); metaStatementHandler = MetaObject.forObject( object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_REFLECTOR_FACTORY); } if (null == dialect || "".equals(dialect)) { logger.warn("Property dialect is not setted,use default 'mysql' "); dialect = defaultDialect; } if (null == pageSqlId || "".equals(pageSqlId)) { logger.warn("Property pageSqlId is not setted,use default '.*Page$' "); pageSqlId = defaultPageSqlId; } MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement"); PageParameter page = null; Object type = metaStatementHandler.getValue("delegate.boundSql.parameterObject"); if (PageParameter.class.isInstance(type)) { page = (PageParameter) type; } // 只重写需要分页的sql语句。通过MappedStatement的ID匹配,默认重写以Page结尾的 // MappedStatement的sql if (mappedStatement.getId().matches(pageSqlId) && page != null && page.getLimit() > 0) { BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql"); Object parameterObject = boundSql.getParameterObject(); if (parameterObject == null) { throw new NullPointerException("parameterObject is null!"); } else { // 分页参数作为参数对象parameterObject的一个属性 String sql = boundSql.getSql(); // 重写sql String pageSql = buildPageSql(sql, page, dialect); metaStatementHandler.setValue("delegate.boundSql.sql", pageSql); // 采用物理分页后,就不需要mybatis的内存分页了,所以重置下面的两个参数 metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET); metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT); Connection connection = (Connection) invocation.getArgs()[0]; // 重设分页参数里的总页数等 setPageParameter(sql, connection, mappedStatement, boundSql, page); } } // 将执行权交给下一个拦截器 return invocation.proceed(); }
public Object intercept(Invocation invocation) throws Throwable { RoutingStatementHandler statementHandler = (RoutingStatementHandler) invocation.getTarget(); BoundSql boundSql = statementHandler.getBoundSql(); MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler); BaseStatementHandler delegate = (BaseStatementHandler) ReflectHelper.getValueByFieldName(statementHandler, "delegate"); MappedStatement mappedStatement = (MappedStatement) ReflectHelper.getValueByFieldName(delegate, "mappedStatement"); Connection connection = (Connection) invocation.getArgs()[0]; // 获取当前准备执行的行边界 RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds"); // 判断是否设置分页 if (rowBounds == null || rowBounds == RowBounds.DEFAULT) { return invocation.proceed(); } Configuration configuration = (Configuration) metaStatementHandler.getValue("delegate.configuration"); Dialect.Type databaseType = null; // 获取当前的数据库方言 try { databaseType = Dialect.Type.valueOf(configuration.getVariables().getProperty("dialect").toUpperCase()); } catch (Exception e) { // ignore throw e; } if (databaseType == null) { throw new RuntimeException( "the value of the dialect property in configuration.xml is not defined : " + configuration.getVariables().getProperty("dialect")); } Dialect dialect = null; // 判断数据库方言 switch (databaseType) { case ORACLE: dialect = new OracleDialect(); } // 原始sql String originalSql = (String) metaStatementHandler.getValue("delegate.boundSql.sql"); // 统计总数 int count = getCount(connection, boundSql, configuration, mappedStatement); Object obj = boundSql.getParameterObject(); if (null != obj && obj instanceof Map) { Map parameterObject = (Map) boundSql.getParameterObject(); parameterObject.put("_dataCount", count); } else { throw new NullPointerException("service中getGridData的condition参数不能为空!"); } // 设置拼接好的分页sql metaStatementHandler.setValue( "delegate.boundSql.sql", dialect.getPageSql(originalSql, rowBounds.getOffset(), rowBounds.getLimit())); // 重置行边界 metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET); metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT); if (log.isDebugEnabled()) { log.debug("生成分页SQL : " + boundSql.getSql()); } return invocation.proceed(); }