JavaWeb中MySQL和Oracle数据库通用分页功能实现完整例子

前言

文章使用了近期比较流行的框架,适合有一定Maven开发经验的读者。
开发工具:Spring Tool Suite
开发环境:SpringBoot+Maven+SSM(三大框架)+JDK1.8
数据库:本文采用Oracle
当然,也可以用Eclipse/MyEclipse,jdk其他版本来开发,记得修改jre和pom配置等问题就行

代码

导入相关依赖包pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.example</groupId>
	<artifactId>page-example</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.3.RELEASE</version>
	</parent>

	<packaging>jar</packaging>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<!-- Import dependency management from Spring Boot -->
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-dependencies</artifactId>
				<version>1.5.3.RELEASE</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
		<mybatisplus-spring-boot-starter.version>1.0.1</mybatisplus-spring-boot-starter.version>
		<fastjson.version>1.2.31</fastjson.version>
		<druid.version>1.0.0</druid.version>
		<commons.io.version>2.5</commons.io.version>
	</properties>

	<dependencies>
		<!--spring boot依赖 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- 这里指定打包的时候不再需要tomcat相关的包 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-cache</artifactId>
		</dependency>
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatisplus-spring-boot-starter</artifactId>
			<version>${mybatisplus-spring-boot-starter.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>com.oracle</groupId>
			<artifactId>ojdbc14</artifactId>
			<version>10.2.0.4.0</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-mail</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<!--其他依赖 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>${fastjson.version}</version>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>${druid.version}</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>${commons.io.version}</version>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<executable>true</executable>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.6</version>
				<configuration>
					<warSourceExcludes>src/main/resources/**</warSourceExcludes>
					<failOnMissingWebXml>false</failOnMissingWebXml>
				</configuration>
			</plugin>
		</plugins>
		<resources>
			<resource>
				<directory>src/main/webapp</directory>
			</resource>
			<resource>
				<directory>src/main/resources</directory>
			</resource>
			<resource>
				<directory>src/main/java</directory>
				<includes>
					<include>**/*.xml</include>
				</includes>
			</resource>
		</resources>
	</build>
</project>
添加Oracle驱动包:/build/lib/ojdbc14-10.2.0.4.0.jar,后面笔者会贴上下载地址(包括本文Demo),也可自行谷百下载。

application-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.2.xsd">
	
	<context:property-placeholder location="classpath:application.properties"/>
	
	<!-- 数据源定义,使用Apache DBCP 连接池 -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
		<property name="driverClassName" value="${jdbc.driver}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
		<property name="initialSize" value="${jdbc.initialSize}" />
		<property name="maxActive" value="${jdbc.maxActive}" />
		<property name="minIdle" value="${jdbc.minIdle}" />
		 <!-- 配置获取连接等待超时的时间 -->     
		<property name="maxWait" value="60000" /> 
		<!-- 是否自动回收超时连接 -->
	    <property name="removeAbandoned" value="true"/>  
		<property name="removeAbandonedTimeout" value="150"/>
		<!-- 是否在自动回收超时连接的时候打印连接的超时错误 -->
		<property name="logAbandoned" value="true"/>
		
		<!-- false : 空闲时是否验证, 若不通过断掉连接, 前提是空闲对象回收器开启状态 -->
		<property name="testWhileIdle" value="true"/>
		<property name="validationQuery" value="SELECT 'x' from dual" /> 
		
		<!-- -1 : 以毫秒表示空闲对象回收器由运行间隔。值为负数时表示不运行空闲对象回收器  若需要回收, 该值最好小于 minEvictableIdleTimeMillis 值  -->
		<property name="timeBetweenEvictionRunsMillis" value="300000"/>
		
		<!--1000*60*30 : 被空闲对象回收器回收前在池中保持空闲状态的最小时间, 毫秒表示 若需要回收, 该值最好小于DB中的 wait_timeout 值 -->
		<property name="minEvictableIdleTimeMillis" value="320000"/>
		
		<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->     
		<property name="poolPreparedStatements" value="true" />     
		<property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
    </bean>
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
	    <property name="dataSource" ref="dataSource"></property>  
	    <property name="configLocation" value="classpath:mybatis-config.xml"></property>
	    <property name="mapperLocations" value="classpath*:/sqlmapper/*.xml" /> 
		<property name="failFast" value="true"></property>  
	    <property name="plugins">  
	        <array>  
	            <bean class="com.page.example.common.PageInterceptor">  
	            </bean>  
	        </array>  
	    </property>
	</bean>
	<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype">  
		<constructor-arg index="0" ref="sqlSessionFactory"/>  
	</bean>
  
	
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.page.example.mapper"/>
		<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
	</bean>
	<!-- 配置事务管理器,注意这里的dataSource和SqlSessionFactoryBean的dataSource要一致,不然事务就没有作用了 -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	    <property name="dataSource" ref="dataSource" />
	</bean>
	<!-- 配置事务的传播特性 -->
	<bean id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
	    <property name="transactionManager" ref="transactionManager" />
	    <property name="transactionAttributes">
	        <props>
	            <prop key="add*">PROPAGATION_REQUIRED</prop>
	            <prop key="edit*">PROPAGATION_REQUIRED</prop>
	            <prop key="remove*">PROPAGATION_REQUIRED</prop>
	            <prop key="insert*">PROPAGATION_REQUIRED</prop>
	            <prop key="update*">PROPAGATION_REQUIRED</prop>
	            <prop key="del*">PROPAGATION_REQUIRED</prop>
	            <prop key="*">readOnly</prop>
	        </props>
	    </property>
	</bean>
	
</beans>
代码已经做了详细的说明,不再赘述。 关键代码是事务配置中文件(mybatis-config.xml/)路径引用和分页拦截器PageInterceptor
application.properties
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc\:oracle\:thin\:@192.168.1.70\:1521\:orcl
jdbc.username=kop
jdbc.password=kop237
jdbc.initialSize=5
jdbc.maxActive=20
jdbc.minIdle=1

server.port=8081
server.contextPath=/page
数据库配置以及服务端口、请求路径
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<properties>
		<property name="dialect" value="oracle" />
	</properties>
	<typeAliases>
		<package name="com.page.example.model" />
	</typeAliases>

</configuration> 
如果想用MySQL,只需修改此处key:dialect对应的value为mysql(或者直接删除该配置,本文代码中默认使用MySQL),还有驱动包
到此,环境就搭建好了。下面进入正题
分页实体类PageQuery.java
package com.page.example.model;

import java.io.Serializable;

public class PageQuery implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	/*页码*/
	private Integer curPageNum;
	/*页总数*/
	private Integer pageSize;
	private Integer startPos;
	private Integer endPos;
	private String sort;
	private String dir;
	
	/**
	 * 总数,如果总数<>0,则表示
	 */
	private Integer totalNum = 0;
	
	public PageQuery(){
	    
	}
	
	public PageQuery(Integer curPageNum, Integer pageSize) {
        this.setPosition(curPageNum, pageSize);
    }

	public Integer getTotalNum() {
		return totalNum;
	}
	
	
	/**
	 * 总数,如果总数<>0,则表示
	 */
	private Integer totalPageNum = 0;


	public Integer getTotalPageNum() {
		return totalPageNum;
	}

	public void setTotalPageNum(Integer totalPageNum) {
		if (totalPageNum == null) {
			totalPageNum = 1;
		}
		this.totalPageNum = totalPageNum;
	}

	public void setTotalNum(Integer totalNum) {
		if (totalNum == null) {
			totalNum = 0;
		}
		this.totalNum = totalNum;
	}

	public Integer getStartPos() {
		return startPos;
	}

	public Integer getEndPos() {
		endPos = startPos + pageSize - 1;
		
		return endPos;
	}

	public void setPosition(Integer curPageNum, Integer pageSize) {
		if (curPageNum == null || curPageNum < 1) {
			curPageNum = 1;
		}
		if (pageSize == null) {
			pageSize = 50;
		}
		this.curPageNum = curPageNum;
		this.pageSize = pageSize;
		startPos = (curPageNum - 1) * pageSize + 1;
		endPos = startPos + pageSize - 1;
	}

	public Integer getCurPageNum() {
		return curPageNum;
	}

	public Integer getPageSize() {
		return pageSize;
	}

	public String getSort() {
		return sort;
	}

	public void setSort(String sort) {
		this.sort = sort;
	}

	public String getDir() {
		return dir;
	}

	public void setDir(String dir) {
		this.dir = dir;
	}

	public void setStartPos(Integer startPos) {
		this.startPos = startPos;
	}

    public void setCurPageNum(Integer curPageNum) {
        this.curPageNum = curPageNum;
    }

    public void setPageSize(Integer pageSize) {
        this.pageSize = pageSize;
    }

    public void setEndPos(Integer endPos) {
        this.endPos = endPos;
    }

    @Override
    public String toString() {
        return "PageQuery [curPageNum=" + curPageNum + ", pageSize=" + pageSize + ", startPos="
                + startPos + ", endPos=" + endPos + ", sort=" + sort + ", dir=" + dir
                + ", totalNum=" + totalNum + ", totalPageNum=" + totalPageNum + "]";
    }
	
}
分页拦截器PageInterceptor.java
package com.page.example.common;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
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.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.ReflectorFactory;
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.scripting.defaults.DefaultParameterHandler;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.page.example.model.PageQuery;

/**
 * 
 * @author fengjk
 *
 */
@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class,Integer.class}) })
public class PageInterceptor implements Interceptor {

    private static final Logger logger = LoggerFactory.getLogger(PageInterceptor.class);
    private static String defaultDialect = "mysql";
    private static String defaultPageSqlId = ".*Page$";
    private String dialect = ""; //数据库方言  
    private String pageSqlId = ""; //mapper.xml中需要拦截的ID(正则匹配) 
    public int pageSize = 10;
    public int curPageNum = 1;
    private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();  
    private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();  
    private static final ReflectorFactory DEFAULT_REFLECT_FACTORY = new DefaultReflectorFactory();  

	public Object intercept(Invocation paramInvocation) throws Throwable {
		StatementHandler statementHandler = (StatementHandler) paramInvocation.getTarget();
		MetaObject metaStatementHandler = MetaObject.forObject(statementHandler, DEFAULT_OBJECT_FACTORY,DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_REFLECT_FACTORY);
		// 分离代理对象链(由于目标类可能被多个拦截器拦截,从而形成多次代理,通过下面的两次循环
		// 可以分离出最原始的的目标类)
		while (metaStatementHandler.hasGetter("h")) {
			Object object = metaStatementHandler.getValue("h");
			metaStatementHandler = MetaObject.forObject(object,DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_REFLECT_FACTORY);
		}
		// 分离最后一个代理对象的目标类
		while (metaStatementHandler.hasGetter("target")) {
			Object object = metaStatementHandler.getValue("target");
			metaStatementHandler = MetaObject.forObject(object,DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_REFLECT_FACTORY);
		}
		Configuration configuration = (Configuration) metaStatementHandler.getValue("delegate.configuration");
		dialect = configuration.getVariables().getProperty("dialect");
		if (null == dialect || "".equals(dialect)) {
			logger.warn("Property dialect is not setted,use default 'mysql' ");
			dialect = defaultDialect;
		}
		pageSqlId = configuration.getVariables().getProperty("pageSqlId");
		if (null == pageSqlId || "".equals(pageSqlId)) {
			pageSqlId = defaultPageSqlId;
		}
		MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
		// 只重写需要分页的sql语句。通过MappedStatement的ID匹配,默认重写以Page结尾的
		// MappedStatement的sql
		if (mappedStatement.getId().matches(pageSqlId)) {
			BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");
			Object parameterObject = boundSql.getParameterObject();
			if (parameterObject == null) {
				throw new NullPointerException("parameterObject is null!");
			} else {
				// 分页参数作为参数对象parameterObject的一个属性
				PageQuery page = (PageQuery) metaStatementHandler.getValue("delegate.boundSql.parameterObject.page");
				if(page.getCurPageNum()<=0 || page.getPageSize()<=0){
					page.setPageSize(pageSize);
					page.setCurPageNum(curPageNum);
				}
				String sql = boundSql.getSql();
				// 重写sql
				String pageSql = this.buildPageSql(sql, page);
				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) paramInvocation.getArgs()[0];
				// 重设分页参数里的总页数等
				this.setPageParameter(sql, connection, mappedStatement, boundSql,page);
			}
		}
		// 将执行权交给下一个拦截器
		return paramInvocation.proceed();
	}

	public Object plugin(Object paramObject) {
		 return Plugin.wrap(paramObject, this);
	}

	public void setProperties(Properties paramProperties) {
		this.dialect = paramProperties.getProperty("dialect");

	}
	private String buildPageSql(String sql, PageQuery page) {
        if (page != null) {
            StringBuilder pageSql = new StringBuilder();
            if ("mysql".equals(dialect)) {
                pageSql = buildPageSqlForMysql(sql, page);
            } else if ("oracle".equals(dialect)) {
                pageSql = buildPageSqlForOracle(sql, page);
            } else {
                return sql;
            }
            return pageSql.toString();
        } else {
            return sql;
        }
    }
	public StringBuilder buildPageSqlForMysql(String sql, PageQuery page) {
        StringBuilder pageSql = new StringBuilder(100);
        String beginrow = String.valueOf((page.getCurPageNum() - 1) * page.getPageSize());
        pageSql.append(sql);
        pageSql.append(" limit " + beginrow + "," + page.getPageSize());
        return pageSql;
    }
	
	public StringBuilder buildPageSqlForOracle(String sql, PageQuery page) {
        StringBuilder pageSql = new StringBuilder(100);
        String beginrow = String.valueOf((page.getCurPageNum() - 1) * page.getPageSize());
        String endrow = String.valueOf(page.getCurPageNum() * page.getPageSize());
        pageSql.append("select * from ( select temp.*, rownum row_id from ( ");
        pageSql.append(sql);
        pageSql.append(" ) temp where rownum <= ").append(endrow);
        pageSql.append(") where row_id > ").append(beginrow);
        return pageSql;
    }
	
	/**
    * 从数据库里查询总的记录数并计算总页数,回写进分页参数<code>PageParameter</code>,这样调用 
    * 者就可用通过 分页参数<code>PageParameter</code>获得相关信息。
    * 
    * @param sql
    * @param connection
    * @param mappedStatement
    * @param boundSql
    * @param page
    */
   private void setPageParameter(String sql, Connection connection, MappedStatement mappedStatement,BoundSql boundSql, PageQuery page) {
       // 记录总记录数
       String countSql = "select count(0) from (" + sql + ")";
       PreparedStatement countStmt = null;
       ResultSet rs = null;
       try {
           countStmt = connection.prepareStatement(countSql);
           BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql,boundSql.getParameterMappings(), boundSql.getParameterObject());
           setParameters(countStmt, mappedStatement, countBS, boundSql.getParameterObject());
           rs = countStmt.executeQuery();
           int totalCount = 0;
           if (rs.next()) {
               totalCount = rs.getInt(1);
           }
           page.setTotalNum(totalCount);
           page.setTotalPageNum(totalCount);
           if(page.getPageSize()>0){
	           int totalPage = totalCount / page.getPageSize() + ((totalCount % page.getPageSize() == 0) ? 0 : 1);
	           page.setTotalPageNum(totalPage);
           }
       } catch (SQLException e) {
           logger.error("Ignore this exception", e);
       } finally {
           try {
        	   if(rs != null){
                   rs.close();
        	   }
           } catch (SQLException e) {
               logger.error("Ignore this exception", e);
           }
           try {
        	   if(countStmt != null){
                   countStmt.close();
        	   }
           } catch (SQLException e) {
               logger.error("Ignore this exception", e);
           }
       }
   }
   /**
    * 对SQL参数(?)设值
    * 
    * @param ps
    * @param mappedStatement
    * @param boundSql
    * @param parameterObject
    * @throws SQLException
    */
   private void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql,
           Object parameterObject) throws SQLException {
       ParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
       parameterHandler.setParameters(ps);
   }

	public String getDialect() {
		return dialect;
	}
	
	public void setDialect(String dialect) {
		this.dialect = dialect;
	}
	
	public String getPageSqlId() {
		return pageSqlId;
	}
	
	public void setPageSqlId(String pageSqlId) {
		this.pageSqlId = pageSqlId;
	}

}
下面就是写个请求的栗子,方便读者理解。
业务实体类RemoteControl.java
package com.page.example.model;

import java.io.Serializable;
import java.util.Date;

import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.DateTimeFormat.ISO;

public class RemoteControl implements Serializable {

	private static final long serialVersionUID = 1L;

	private Long id;  // ID

	private String electricalroomname;  // 电房名称

	private Short feederid;  // 馈线ID
	
	private String feedername; // 馈线名称

	private String devicevender;  // 终端厂家

	private Byte commmode;  // 通信方式
	
	private Date planprocesstime;  // 计划操作日期

	private String rmtprocesscontent;  // 三遥操作内容

	private Integer prjproperty;  // 工程性质

	private String checkresult;  // 核实情况

	private String feedback;  // 具体反馈信息
	
	@DateTimeFormat(iso= ISO.DATE)
	private Date realprocesstime;  // 实际操作时间

	private String operator;  // 操作员

	private Integer result;  // 遥控结果
	
	private Date createtime;  // 创建时间
	
	private Date beginTime;
	
	private Date endTime;

	public String getFeedername() {
		return feedername;
	}


	public void setFeedername(String feedername) {
		this.feedername = feedername;
	}


	public Date getBeginTime() {
		return beginTime;
	}


	public void setBeginTime(Date beginTime) {
		this.beginTime = beginTime;
	}


	public Date getEndTime() {
		return endTime;
	}


	public void setEndTime(Date endTime) {
		this.endTime = endTime;
	}


	public Long getId() {
		return id;
	}

    public void setId(Long id) {
    	this.id = id;
    }

	public String getElectricalroomname() {
		return electricalroomname;
	}

    public void setElectricalroomname(String electricalroomname) {
    	this.electricalroomname = electricalroomname;
    }

	public Short getFeederid() {
		return feederid;
	}

    public void setFeederid(Short feederid) {
    	this.feederid = feederid;
    }

	public String getDevicevender() {
		return devicevender;
	}

    public void setDevicevender(String devicevender) {
    	this.devicevender = devicevender;
    }

	public Byte getCommmode() {
		return commmode;
	}

    public void setCommmode(Byte commmode) {
    	this.commmode = commmode;
    }

	public Date getPlanprocesstime() {
		return planprocesstime;
	}

    public void setPlanprocesstime(Date planprocesstime) {
    	this.planprocesstime = planprocesstime;
    }

	public String getRmtprocesscontent() {
		return rmtprocesscontent;
	}

    public void setRmtprocesscontent(String rmtprocesscontent) {
    	this.rmtprocesscontent = rmtprocesscontent;
    }

	public Integer getPrjproperty() {
		return prjproperty;
	}

    public void setPrjproperty(Integer prjproperty) {
    	this.prjproperty = prjproperty;
    }

	public String getCheckresult() {
		return checkresult;
	}

    public void setCheckresult(String checkresult) {
    	this.checkresult = checkresult;
    }

	public String getFeedback() {
		return feedback;
	}

    public void setFeedback(String feedback) {
    	this.feedback = feedback;
    }

	public Date getRealprocesstime() {
		return realprocesstime;
	}

    public void setRealprocesstime(Date realprocesstime) {
    	this.realprocesstime = realprocesstime;
    }

	public String getOperator() {
		return operator;
	}

    public void setOperator(String operator) {
    	this.operator = operator;
    }

	public Integer getResult() {
		return result;
	}

    public void setResult(Integer result) {
    	this.result = result;
    }

	public Date getCreatetime() {
		return createtime;
	}

    public void setCreatetime(Date createtime) {
    	this.createtime = createtime;
    }
	
	@Override
	public String toString() {
		String log = ""; 
		log += "[id:" + getId() + "]";
		log += "[electricalroomname:" + getElectricalroomname() + "]";
		log += "[feederid:" + getFeederid() + "]";
		log += "[devicevender:" + getDevicevender() + "]";
		log += "[commmode:" + getCommmode() + "]";
		log += "[planprocesstime:" + getPlanprocesstime() + "]";
		log += "[rmtprocesscontent:" + getRmtprocesscontent() + "]";
		log += "[prjproperty:" + getPrjproperty() + "]";
		log += "[checkresult:" + getCheckresult() + "]";
		log += "[feedback:" + getFeedback() + "]";
		log += "[realprocesstime:" + getRealprocesstime() + "]";
		log += "[operator:" + getOperator() + "]";
		log += "[result:" + getResult() + "]";
		log += "[createtime:" + getCreatetime() + "]";
		log += super.toString();
		return log;
	}
}
RemoteControlMapper.java
package com.page.example.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Param;

import com.page.example.model.PageQuery;
import com.page.example.model.RemoteControl;

public interface RemoteControlMapper {
    
    List<RemoteControl> getRemoteControlPage(@Param("page")PageQuery pageQuery);
    
}
RemoteControlMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.page.example.mapper.RemoteControlMapper">
	<!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        <![CDATA[id,electricalroomname,feederid,devicevender,commmode,planprocesstime,rmtprocesscontent,prjproperty,checkresult,feedback,realprocesstime,operator,result,createtime]]> 
    </sql>
	
    <resultMap id="BaseResultMap" type="RemoteControl">
		<id column="ID" property="id" />
		<result column="ELECTRICALROOMNAME" property="electricalroomname" />
		<result column="FEEDERID" property="feederid" />
		<result column="DEVICEVENDER" property="devicevender" />
		<result column="COMMMODE" property="commmode" />
		<result column="PLANPROCESSTIME" property="planprocesstime" />
		<result column="RMTPROCESSCONTENT" property="rmtprocesscontent" />
		<result column="PRJPROPERTY" property="prjproperty" />
		<result column="CHECKRESULT" property="checkresult" />
		<result column="FEEDBACK" property="feedback" />
		<result column="REALPROCESSTIME" property="realprocesstime" />
		<result column="OPERATOR" property="operator" />
		<result column="RESULT" property="result" />
		<result column="CREATETIME" property="createtime" />
    </resultMap>
	
	<select id="getRemoteControlPage" resultType="RemoteControl">
        select <include refid="Base_Column_List" /> from REMOTE_CONTROL where 1 = 1
    </select>
    
</mapper>
对外接口RemoteControlController.java
package com.page.example.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.page.example.mapper.RemoteControlMapper;
import com.page.example.model.PageQuery;
import com.page.example.model.RemoteControl;

/**
 * 
 * @author fengjk
 * @date 2017-07-17
 */
@Controller
@RequestMapping(value = "/other/remoteControl")
public class RemoteControlController {
    
    @Resource
    private RemoteControlMapper remoteControlMapper;
    
    @RequestMapping(value = "/list", method = { RequestMethod.POST })
    @ResponseBody
    public JSONObject list( @RequestBody JSONObject paramObject) {
    	int page = paramObject.getIntValue("page");
		int size = paramObject.getIntValue("size");
		if (page == 0) {
			page = 1;
		}
		if (size == 0) {
			size = 10;
		}
		PageQuery pageQuery = new PageQuery(page, size);
        List<RemoteControl> result = remoteControlMapper.getRemoteControlPage(pageQuery);
        
        Map<String, Object> resultMap = new HashMap<String, Object>();
		resultMap.put("total", pageQuery.getTotalNum());
		resultMap.put("content", result);
		
		JSONObject resultObject = new JSONObject();
		resultObject.put("result_data", resultMap);
        return resultObject;
    }
    
}
启动类PageApplication.java
package com.page.example;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ImportResource;

/**
 * 启动类
 * 
 */
@SpringBootApplication
@ComponentScan({"com.page.example"})
@ImportResource({"classpath:application-context.xml"})
public class PageApplication extends SpringBootServletInitializer{

    protected final static Logger logger = LoggerFactory.getLogger(PageApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(PageApplication.class, args);
        logger.info("PageApplication is sussess!");
    }
}
这个尤为重要,能不能运行就靠它了。@ComponentScan扫描实体和mapper映射文件,@ImportResource顾名思义。最后启动服务。(PageApplication.java右键--Run As--Java Application)

模拟测试调用接口,笔者用的是谷歌apizza插件工具

也可以不传参数,代码中默认page:1,size:10。page为页码,size为每页条数(此处查询第1页10条数据)。total为表数据总数,content为返回数据。

Error(附上笔者踩过的坑)


RemoteControlMapper.xml中空间命名namespace路径错误或者DML方法名、参数和mapper中不一致。


以上情况是由于Mybatis版本问题,3.4.4以下版本StatementHandler没有transactionTimeout参数,forObject没有ReflectorFactory。注意:使用Mybatis3.4.4以下版本只需把这两个地方参数去掉,反之,同理

总结

近期比较忙碌,一直没时间整理,终于腾出时间自己搭建一套框架,顺便就分享一下后台开发中常见的分页功能实现,笔者感觉光是搭建项目都能给读者带来帮助,避免踩坑,同样也适合SpringBoot初学者,后期附上Demo下载地址,文章如有笔误,请及时联系笔者,万分感谢,欢迎加qq群学习交流:583138104
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值