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(); }
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); } } } } }
/** * 获取一个Mybatis运行时调用的SQL和参数 * * @param ms * @param parameterObject * @return */ public static MyBatisSql getMyBatisSql(MappedStatement ms, Object parameterObject) { MyBatisSql ibatisSql = new MyBatisSql(); BoundSql boundSql = ms.getBoundSql(parameterObject); ibatisSql.setSql(boundSql.getSql()); List<ParameterMapping> parameterMappings = boundSql.getParameterMappings(); if (parameterMappings != null) { Object[] parameterArray = new Object[parameterMappings.size()]; MetaObject metaObject = parameterObject == null ? null : MetaObject.forObject(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(); PropertyTokenizer prop = new PropertyTokenizer(propertyName); if (parameterObject == null) { value = null; } else if (ms.getConfiguration() .getTypeHandlerRegistry() .hasTypeHandler(parameterObject.getClass())) { value = parameterObject; } else if (boundSql.hasAdditionalParameter(propertyName)) { value = boundSql.getAdditionalParameter(propertyName); } else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX) && boundSql.hasAdditionalParameter(prop.getName())) { value = boundSql.getAdditionalParameter(prop.getName()); if (value != null) { value = MetaObject.forObject(value) .getValue(propertyName.substring(prop.getName().length())); } } else { value = metaObject == null ? null : metaObject.getValue(propertyName); } parameterArray[i] = value; } } ibatisSql.setParameters(parameterArray); } return ibatisSql; }
@Override public void handleResult(ResultContext context) { // TODO is that assignment always true? // 得到一条记录 // 这边黄色警告没法去掉了?因为返回Object型 final V value = (V) context.getResultObject(); // MetaObject.forObject,包装一下记录 // MetaObject是用反射来包装各种类型 final MetaObject mo = MetaObject.forObject(value, objectFactory, objectWrapperFactory); // TODO is that assignment always true? final K key = (K) mo.getValue(mapKey); mappedResults.put(key, value); // 这个类主要目的是把得到的List转为Map }
@Test public void shouldUseObjectWrapperFactoryWhenSet() { MetaObject meta = MetaObject.forObject( new Author(), SystemMetaObject.DEFAULT_OBJECT_FACTORY, new CustomBeanWrapperFactory(), new DefaultReflectorFactory()); assertTrue(meta.getObjectWrapper().getClass().equals(CustomBeanWrapper.class)); // Make sure the old default factory is in place and still works meta = SystemMetaObject.forObject(new Author()); assertFalse(meta.getObjectWrapper().getClass().equals(CustomBeanWrapper.class)); }
@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; }
@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(); }
/** * 获取操作员id <功能详细描述> * * @return [参数说明] * @return String [返回类型说明] * @exception throws [异常类型] [异常说明] * @see [类、类#方法、类#成员] */ private void setOperatorInfo(Map<String, Object> attributes) { ServiceLoggerSessionContext context = ServiceLoggerSessionContext.getContext(); if (context.getRequest() == null || context.getRequest().getSession(false) == null) { attributes.put("operatorLoginName", ""); attributes.put("operatorName", ""); } else { HttpSession session = context.getRequest().getSession(false); Object operatorObj = session.getAttribute("operator"); if (operatorObj != null) { MetaObject metaObject = MetaObject.forObject(operatorObj); Object loginName = metaObject.getValue("loginName"); Object userName = metaObject.getValue("userName"); attributes.put("operatorLoginName", loginName == null ? "" : (String) loginName); attributes.put("operatorName", userName == null ? "" : (String) userName); } else { attributes.put("operatorLoginName", ""); attributes.put("operatorName", ""); } } }
@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(); }