[Java][MyBatis] page implementation

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

[Java][MyBatis]Physical page implementation

For some time the Mybatis3.0 out, I quite like a persistence framework that, because it is simple and practical, low cost. Mybatis3.0 in the whole structure and almost ibatis2.X, improved characteristics as follows:

1 Analysis of XML introduced Xpath, unlike ibatis2.x, amateur

2 dynamic SQL OGNL analysis

3 adding annotations to configure SQL, did not feel what great use, I like XML, code and configuration, this is also the original intention of ibatis

4 to strengthen the function of the cache. Mybatis3.0 cache module breaks, divided into "persistent implementation (prepetual)" and "resource recovery strategy (eviction)", better for their combination and extension of the cache function

5 finally joined the plugin function, like struts, this can be a very good extension of the internal Executor,, StatementHandler... Internal object function.



MyBatis paging functionality is based on memory paging(Find out all the records and then remove the offset of the record, if the JDBC drive support absolute or rs.next () to the specified offset), In fact, paging achieve basic useless, especially a large number of data cases. Paging function, realize the physical page but we can extend MyBatis by plugin function. The specific practices are as follows:

1, Write page plug-in class:

/**
 * Copyright: Huaxin software
 * Project Name: the ACWS framework classes
 * Creator: Wangdf
 * Date: 2014-4-2
 * Documentation: ACWS framework paging interface class
 */
package framework.core.interceptor;

import java.sql.Connection;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.collections.MapUtils;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.RowBounds;

import framework.core.util.DBUtil;

/**
 * The framework of ACWS page interface class
 * @author Wangdf
 *
 */
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class PaginationInterceptor implements Interceptor {
    private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
    private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();

	@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);

		RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds");
		if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
			return invocation.proceed();
		}
		
        // Separating agent object chain (due to the target class may be more interceptors, thereby forming a multiple agent, after two cycles of the following can be separated from the original target class)
        while (metaStatementHandler.hasGetter("h")) {
            Object object = metaStatementHandler.getValue("h");
            metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
        }
        // The final separation of a proxy object target class
        while (metaStatementHandler.hasGetter("target")) {
            Object object = metaStatementHandler.getValue("target");
            metaStatementHandler = MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
        }

        BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");
        
    	String sql = boundSql.getSql();
		StringBuffer sbSql = new StringBuffer();

    	// Rewrite SQL
		Configuration configuration = (Configuration)metaStatementHandler.getValue("delegate.configuration");
		DBUtil dbUtil = new DBUtil(configuration);
        if(dbUtil.isMySQL()){
        	sbSql.append(sql).append(" LIMIT ").append(rowBounds.getOffset()).append(", ").append(rowBounds.getLimit());
            metaStatementHandler.setValue("delegate.boundSql.sql", sbSql.toString());
            
            // The physical page, do not need mybatis paging, so the two parameter resetting the following
            metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
            metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
		} else if(dbUtil.isOracle()){
			sbSql.append("SELECT * ");
			sbSql.append("  FROM (SELECT ROWNUM RN, NOPAGESQL.*   ");
			sbSql.append("          FROM (").append(sql).append(") NOPAGESQL ");
			sbSql.append("         WHERE ROWNUM <= ").append(rowBounds.getLimit()+rowBounds.getOffset()).append(")");
			sbSql.append(" WHERE RN >= ").append(rowBounds.getOffset());
	        metaStatementHandler.setValue("delegate.boundSql.sql", sbSql.toString());
	        
	        // The physical page, do not need mybatis paging, so the two parameter resetting the following
	        metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
	        metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
		} else {
			
		}
        
        // The executive power to an interceptor
        return invocation.proceed();
	}

	@Override
	public Object plugin(Object target) {
        // When the target is a StatementHandler type, before packing the target class, or directly to the target itself, reduce the number of target is agent
        if (target instanceof StatementHandler) {
            return Plugin.wrap(target, this);
        } else {
            return target;
        }
	}

	@Override
	public void setProperties(Properties properties) {
		// TODO Auto-generated method stub
		
	}

}

2, The configuration read class

/**
 * Copyright: Huaxin software
 * Project Name: the ACWS framework classes
 * Creator: Wangdf
 * Date: 2014-4-2
 * Documentation: ACWS framework database tools
 */
package framework.core.util;

import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The framework of ACWS database tool
 * @author Wangdf
 */
public class DBUtil {
	private static final String DBTYPE_MYSQL = "MySQL";//The type of support: MySQL,Oracle
	private static final String DBTYPE_ORACLE = "Oracle";//The type of support: MySQL,Oracle

	private static Logger logger = LoggerFactory.getLogger(DBUtil.class);
	private Configuration configuration = null;
	
	private String dbType = "";
	private String defaultDateFormat = "";
	
	public DBUtil(Configuration configuration){
		if(configuration == null){
			logger.error("The system boot failure: MyBatis Configuration object is null!");
			throw new IllegalArgumentException("The system boot failure: MyBatis Configuration object is null!");
		}
		this.configuration = configuration;
		this.dbType = this.configuration.getVariables().getProperty("dbtype");
	    if(StringUtils.isBlank(dbType)){
	    	logger.error("The type of database is not configured!");
	    } else {
	    	logger.info("For database types: "+dbType);
	    }
		this.defaultDateFormat = this.configuration.getVariables().getProperty("defaultDateFormat");
	    if(StringUtils.isBlank(this.defaultDateFormat)){
	    	this.defaultDateFormat="yyyy-MM-dd";
	    	logger.info("The date format string does not specify a default database! The system default: yyyy-MM-dd");
	    } else {
	    	logger.info("Database default date format string: "+this.defaultDateFormat);
	    }
	}
	
	/**
	 * To determine whether the Oracle database
	 * @return
	 * @author wangdf
	 */
	public boolean isOracle(){
		return DBTYPE_ORACLE.equals(this.dbType);
	}
	
	
	/**
	 * To determine whether the MySQL database
	 * @return
	 * @author wangdf
	 */
	public boolean isMySQL(){
		return DBTYPE_MYSQL.equals(this.dbType);
	}
	
	/**
	 * Get database types
	 * @return
	 * @author wangdf
	 */
	public String getDbType(){
		return this.dbType;
	}
	
	
	/**
	 * To get the default date format
	 * @return
	 * @author wangdf
	 */
	public String getDefaultDateFormat(){
		return this.defaultDateFormat;
	}

}

3, Set in the mybatis global configuration file

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" " ;>
<configuration>
	
	<properties>
	    <property name="dbtype" value="MySQL"/><!-- The type of database: MySQL, Oracle -->
	    <property name="defaultDateFormat" value="yyyy-MM-dd"/>
	</properties>

	<settings>
		<setting name="cacheEnabled" value="true" />
		<setting name="lazyLoadingEnabled" value="true" />
		<setting name="multipleResultSetsEnabled" value="true" />
		<setting name="useColumnLabel" value="true" />
		<setting name="defaultExecutorType" value="REUSE" />
		<setting name="defaultStatementTimeout" value="25000" />
	</settings>
	
	<plugins>
		<plugin interceptor="framework.core.interceptor.PaginationInterceptor"></plugin>
	</plugins>
</configuration>



Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by John at August 21, 2014 - 4:55 PM