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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章