版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sun_shaoping/article/details/69392217
声明
欢迎转载请注明原文地址,谢谢。
简介
sybase数据库本身是不支持分页sql语句,想用mybatis操作sybase分页很麻烦,在网上也看了不少使用数据库存储过程解决的。
但总觉得局限性太大出现很多问题,所以本文介绍结合mybatis进行游标分页处理,不影响mybatis本身写法的限制,
只需遵循分页接口规范即可(可支持多数据库分页,不过效率没有数据库本身分页效率高)。
本文源码地址:https://github.com/ssp1523/sybase-mybatis-pagination,最好先下载源码结合文本效果更佳。
第一步:创建maven web项目
maven pom文件配置
<?xml version="1.0" encoding="UTF-8"?>
<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.smp</groupId>
<artifactId>sybase-mybatis-pagination</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<description>Mybatis 基于sybase数据库游标分页例子</description>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<javax-activation.version>1.1</javax-activation.version>
<spring.version>4.0.4.RELEASE</spring.version>
<mysql-connector-java.version>5.1.34</mysql-connector-java.version>
<java.version>1.7</java.version>
</properties>
<dependencies>
<!-- spring start -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-dao</artifactId>
<version>2.0.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-mock</artifactId>
<version>2.0.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring end -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>net.sourceforge.jtds</groupId>
<artifactId>jtds</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
</dependencies>
</project>
web.xml文件配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>springMvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/ApplicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
resources/spring/ApplicationContext.xml spring xml文件配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 启用注解 -->
<context:annotation-config/>
<context:component-scan base-package="com.smp"/>
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:dbconfig.properties" />
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</bean>
<!-- 配置mybatis -->
<bean id="sqlSessionFactory"
class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- mapper扫描 -->
<property name="mapperLocations" value="classpath:com/smp/mapper/*.xml"/>
</bean>
<!--mapper扫描-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.smp.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
<bean id="sqlSessionTemplate"
class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory"/>
</bean>
</beans>
第二步:创建分页相关配置和java类
数据库连接配置文件 resources/dbconfig.properties,由于是演示项目所以配置较简单
url=你的数据库url地址
driverClassName=net.sourceforge.jtds.jdbc.Driver
username=你的数据库用户名
password=你的数据库密码
分页核心类 SybasePagination
package com.smp;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.jdbc.core.*;
import org.springframework.jdbc.datasource.AbstractDataSource;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
/**
* sybase 分页
* Created by ssp on 2017/3/17.
*/
@Component
public class SybasePagination {
@Resource(name = "sqlSessionFactory")
private SqlSessionFactory sqlSessionFactory;
private BoundSql getBoundSql(String mapperId, Object parameter) {
return getMappedStatement(mapperId).getBoundSql(parameter);
}
private MappedStatement getMappedStatement(String mapperId) {
return sqlSessionFactory.getConfiguration().getMappedStatement(mapperId);
}
/**
* mybatis游标分页方法
* @param mapperId mybatis 映射id 如:com.smp.mapper.CustomMapper.findByListPage
* @param params 分页参数 暂时只支持Page类型参数
* @return 分页结果
*/
public List<PageData> listPage(String mapperId, Object params) throws SQLException, NoSuchFieldException, IllegalAccessException {
return queryForListPage(sqlSessionFactory.openSession().getConnection(), getBoundSql(mapperId, params), getMappedStatement(mapperId), (Page) params);
}
/**
* 分页核心方法,处理游标分页操作
* 由于是使用jdbc游标分页,所以此处使用JdbcTemplate简化操作。
* @param connection 数据库连接
* @param boundSql 分页BoundSql
* @param mappedStatement 分页 MappedStatement
* @param page 分页Page类
* @return 分页结果
*/
@SuppressWarnings("unchecked")
private List<PageData> queryForListPage(final Connection connection, final BoundSql boundSql, final MappedStatement mappedStatement, final Page page) throws SQLException, NoSuchFieldException, IllegalAccessException {
//分页count
PagePlugin.pageCount(connection, mappedStatement, boundSql, page);
return (List) new JdbcTemplate(new JdbcTemplateDataSource(connection))
.query(new MyPreparedStatementCreator(boundSql, mappedStatement, page)
, new RowMapperResultSetExtractor(new ColumnPageDataRowMapper(page)) {
@Override
public List extractData(ResultSet rs) throws SQLException {
if (page.getCurrentResult() != 0) {
//将游标移动到第一条记录
rs.first();
// 游标移动到要输出的第一条记录
rs.relative(page.getCurrentResult() - 1);
}
return super.extractData(rs);
}
});
}
private class JdbcTemplateDataSource extends AbstractDataSource {
private Connection connection;
JdbcTemplateDataSource(Connection connection) {
this.connection = connection;
}
public Connection getConnection() throws SQLException {
return connection;
}
public Connection getConnection(String username, String password) throws SQLException {
return connection;
}
}
private class MyPreparedStatementCreator implements PreparedStatementCreator {
private BoundSql boundSql;
private MappedStatement mappedStatement;
private Page page;
MyPreparedStatementCreator(BoundSql boundSql, MappedStatement mappedStatement, Page page) {
this.boundSql = boundSql;
this.mappedStatement = mappedStatement;
this.page = page;
}
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement pstat = con.prepareStatement(boundSql.getSql(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
PagePlugin.setParameters(pstat, mappedStatement, boundSql, boundSql.getParameterObject());
pstat.setMaxRows(page.getCurrentResult() + page.getShowCount());
return pstat;
}
}
private class ColumnPageDataRowMapper implements RowMapper<PageData> {
private Page page;
ColumnMapRowMapper columnMapRowMapper = new ColumnMapRowMapper() {
@Override
protected Map<String, Object> createColumnMap(int columnCount) {
return new PageData();
}
@Override
protected String getColumnKey(String columnName) {
if (page.getCamelName())
return StringUtil.camelName(columnName);
else
return super.getColumnKey(columnName);
}
};
private ColumnPageDataRowMapper(Page page) {
this.page = page;
}
public PageData mapRow(ResultSet rs, int rowNum) throws SQLException {
return (PageData) columnMapRowMapper.mapRow(rs, rowNum);
}
}
}
Page分页vo类,存储分页相关信息,作为分页参数使用
package com.smp;
public class Page {
private int showCount; //每页显示记录数
private int totalPage; //总页数
private int totalResult; //总记录数
private int currentPage; //当前页
private int currentResult; //当前记录起始索引
private boolean entityOrField; //true:需要分页的地方,传入的参数就是Page实体;false:需要分页的地方,传入的参数所代表的实体拥有Page属性
private PageData pd = new PageData();
private Boolean camelName = false;
public Page() {
}
public int getTotalPage() {
if (totalResult % showCount == 0)
totalPage = totalResult / showCount;
else
totalPage = totalResult / showCount + 1;
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getTotalResult() {
return totalResult;
}
public void setTotalResult(int totalResult) {
this.totalResult = totalResult;
}
public int getCurrentPage() {
if (currentPage <= 0)
currentPage = 1;
if (currentPage > getTotalPage())
currentPage = getTotalPage();
return currentPage;
}
public void setCurrentPage(int currentPage) {
this.currentPage = currentPage;
}
public int getShowCount() {
return showCount;
}
public void setShowCount(int showCount) {
this.showCount = showCount;
}
public int getCurrentResult() {
currentResult = (getCurrentPage() - 1) * getShowCount();
if (currentResult < 0)
currentResult = 0;
return currentResult;
}
public void setCurrentResult(int currentResult) {
this.currentResult = currentResult;
}
public boolean isEntityOrField() {
return entityOrField;
}
public void setEntityOrField(boolean entityOrField) {
this.entityOrField = entityOrField;
}
public PageData getPd() {
return pd;
}
public void setPd(PageData pd) {
this.pd = pd;
}
public Boolean getCamelName() {
return camelName;
}
public void setCamelName(Boolean camelName) {
this.camelName = camelName;
}
}
PageData类,分页查询的方法结果一条记录为一个PageData
package com.smp;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class PageData extends HashMap<String, Object> implements Map<String, Object> {
private static final long serialVersionUID = 1L;
private Map<String, Object> map = null;
public PageData() {
map = new HashMap<>();
}
@Override
public Object get(Object key) {
return map.get(key);
}
public String getString(Object key) {
return (String) get(key);
}
@SuppressWarnings("unchecked")
@Override
public Object put(String key, Object value) {
return map.put(key, value);
}
@Override
public Object remove(Object key) {
return map.remove(key);
}
public void clear() {
map.clear();
}
public boolean containsKey(Object key) {
return map.containsKey(key);
}
public boolean containsValue(Object value) {
return map.containsValue(value);
}
public Set<Map.Entry<String, Object>> entrySet() {
return map.entrySet();
}
public boolean isEmpty() {
return map.isEmpty();
}
public Set<String> keySet() {
return map.keySet();
}
@SuppressWarnings("unchecked")
public void putAll(Map t) {
map.putAll(t);
}
public int size() {
return map.size();
}
public Collection<Object> values() {
return map.values();
}
}
PagePlugin类,分页工具类,处理总条数和参数设置。
package com.smp;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.property.PropertyTokenizer;
import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
class PagePlugin {
static void pageCount(Connection connection, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject) throws NoSuchFieldException, IllegalAccessException, SQLException {
String countSql = "select count(0) from (" + sqlProcess(boundSql.getSql()) + ") tmp_count"; //记录统计 == oracle 加 as 报错(SQL command not properly ended)
PreparedStatement countStmt = connection.prepareStatement(countSql);
BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql, boundSql.getParameterMappings(), parameterObject);
setParameters(countStmt, mappedStatement, countBS, parameterObject);
ResultSet rs = countStmt.executeQuery();
int count = 0;
if (rs.next()) {
count = rs.getInt(1);
}
rs.close();
countStmt.close();
Page page;
if (parameterObject instanceof Page) { //参数就是Page实体
page = (Page) parameterObject;
page.setEntityOrField(true);
page.setTotalResult(count);
} else { //参数为某个实体,该实体拥有Page属性
Field pageField = ReflectHelper.getFieldByFieldName(parameterObject, "page");
if (pageField != null) {
page = (Page) ReflectHelper.getValueByFieldName(parameterObject, "page");
if (page == null)
page = new Page();
page.setEntityOrField(false);
page.setTotalResult(count);
ReflectHelper.setValueByFieldName(parameterObject, "page", page); //通过反射,对实体对象设置分页对象
} else {
throw new NoSuchFieldException(parameterObject.getClass().getName() + "不存在 page 属性!");
}
}
}
/**
* sql处理
*
* @param sql 被处理的sql
* @return 处理后的sql语句
*/
private static String sqlProcess(String sql) {
//去掉sql语句 order by 语句
int orderIndex;
if ((orderIndex = sql.toLowerCase().lastIndexOf("order")) != -1) {
return sql.substring(0, orderIndex);
}
return sql;
}
/**
* 对SQL参数(?)设值,参考org.apache.ibatis.executor.parameter.DefaultParameterHandler
*/
@SuppressWarnings("unchecked")
static void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject) throws SQLException {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
Configuration configuration = mappedStatement.getConfiguration();
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(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 (typeHandlerRegistry.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 = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length()));
}
} else {
value = metaObject == null ? null : metaObject.getValue(propertyName);
}
TypeHandler typeHandler = parameterMapping.getTypeHandler();
if (typeHandler == null) {
throw new ExecutorException("There was no TypeHandler found for parameter " + propertyName + " of statement " + mappedStatement.getId());
}
typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());
}
}
}
}
}
ReflectHelper类,反射工具类
package com.smp;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.property.PropertyTokenizer;
import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
class PagePlugin {
static void pageCount(Connection connection, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject) throws NoSuchFieldException, IllegalAccessException, SQLException {
String countSql = "select count(0) from (" + sqlProcess(boundSql.getSql()) + ") tmp_count"; //记录统计 == oracle 加 as 报错(SQL command not properly ended)
PreparedStatement countStmt = connection.prepareStatement(countSql);
BoundSql countBS = new BoundSql(mappedStatement.getConfiguration(), countSql, boundSql.getParameterMappings(), parameterObject);
setParameters(countStmt, mappedStatement, countBS, parameterObject);
ResultSet rs = countStmt.executeQuery();
int count = 0;
if (rs.next()) {
count = rs.getInt(1);
}
rs.close();
countStmt.close();
Page page;
if (parameterObject instanceof Page) { //参数就是Page实体
page = (Page) parameterObject;
page.setEntityOrField(true);
page.setTotalResult(count);
} else { //参数为某个实体,该实体拥有Page属性
Field pageField = ReflectHelper.getFieldByFieldName(parameterObject, "page");
if (pageField != null) {
page = (Page) ReflectHelper.getValueByFieldName(parameterObject, "page");
if (page == null)
page = new Page();
page.setEntityOrField(false);
page.setTotalResult(count);
ReflectHelper.setValueByFieldName(parameterObject, "page", page); //通过反射,对实体对象设置分页对象
} else {
throw new NoSuchFieldException(parameterObject.getClass().getName() + "不存在 page 属性!");
}
}
}
/**
* sql处理
*
* @param sql 被处理的sql
* @return 处理后的sql语句
*/
private static String sqlProcess(String sql) {
//去掉sql语句 order by 语句
int orderIndex;
if ((orderIndex = sql.toLowerCase().lastIndexOf("order")) != -1) {
return sql.substring(0, orderIndex);
}
return sql;
}
/**
* 对SQL参数(?)设值,参考org.apache.ibatis.executor.parameter.DefaultParameterHandler
*/
@SuppressWarnings("unchecked")
static void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject) throws SQLException {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings != null) {
Configuration configuration = mappedStatement.getConfiguration();
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(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 (typeHandlerRegistry.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 = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length()));
}
} else {
value = metaObject == null ? null : metaObject.getValue(propertyName);
}
TypeHandler typeHandler = parameterMapping.getTypeHandler();
if (typeHandler == null) {
throw new ExecutorException("There was no TypeHandler found for parameter " + propertyName + " of statement " + mappedStatement.getId());
}
typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType());
}
}
}
}
}
StringUtil类,字符串工具类
package com.smp;
/**
* 字符串相关方法
*
*/
public class StringUtil {
/**
* 将以逗号分隔的字符串转换成字符串数组
* @param valStr
* @return String[]
*/
public static String[] StrList(String valStr){
int i = 0;
String TempStr = valStr;
String[] returnStr = new String[valStr.length() + 1 - TempStr.replace(",", "").length()];
valStr = valStr + ",";
while (valStr.indexOf(',') > 0)
{
returnStr[i] = valStr.substring(0, valStr.indexOf(','));
valStr = valStr.substring(valStr.indexOf(',')+1 , valStr.length());
i++;
}
return returnStr;
}
/**
* 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。</br>
* 例如:HELLO_WORLD->helloWorld
*
* @param name 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串
*/
public static String camelName(String name) {
StringBuilder result = new StringBuilder();
// 快速检查
if (name == null || name.isEmpty()) {
// 没必要转换
return "";
} else if (!name.contains("_")) {
// 不含下划线,仅将首字母小写
return name.substring(0, 1).toLowerCase() + name.substring(1);
}
// 用下划线将原始字符串分割
String camels[] = name.split("_");
for (String camel : camels) {
// 跳过原始字符串中开头、结尾的下换线或双重下划线
if (camel.isEmpty()) {
continue;
}
// 处理真正的驼峰片段
if (result.length() == 0) {
// 第一个驼峰片段,全部字母都小写
result.append(camel.toLowerCase());
} else {
// 其他的驼峰片段,首字母大写
result.append(camel.substring(0, 1).toUpperCase());
result.append(camel.substring(1).toLowerCase());
}
}
return result.toString();
}
}
PaginationMapper类,Mapper分页接口,需要分页的Mapper类继承该类。
package com.smp.mapper;
import com.smp.Page;
import com.smp.PageData;
import java.util.List;
/**
* 分页mapper
* Created by ssp on 2017/3/18.
*/
public interface PaginationMapper{
List<PageData> findByListPage(Page page);
}
第三步:创建分页测试类及数据
使用Custom进行分页测试
首先创建 Custom 实体
package com.smp;
public class Custom {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
Service,Controller,Mapper,xml
package com.smp;
import com.smp.mapper.CustomMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
@Service
public class CustomService {
@Autowired
private CustomMapper customMapper;
@Autowired
private SybasePagination sybasePagination;
List<PageData> findByListPage(Page page){
try {
return sybasePagination.listPage(CustomMapper.class.getName() + ".findByListPage", page);
} catch (SQLException | NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
return Collections.emptyList();
}
}
package com.smp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class CustomController {
@Autowired
private CustomService customService;
@RequestMapping("/page")
public void page(){
Page page = new Page();
//字段名称转换成小驼峰式true,不转换为false
page.setCamelName(true);
//设置当前是第几页
page.setCurrentPage(2);
//每页有多条数据
page.setShowCount(5);
// page.getPd().put("lastName", "1");
List<PageData> byListPage = customService.findByListPage(page);
System.out.println("一页条数:"+byListPage.size());
System.out.println("本页内容:"+byListPage);
System.out.println("总记录数:"+page.getTotalResult());
}
}
package com.smp.mapper;
import org.springframework.stereotype.Repository;
@Repository
public interface CustomMapper extends PaginationMapper {
}
<?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.smp.mapper.CustomMapper">
<resultMap id="custom" type="com.smp.Custom">
<result column="first_name" property="firstName"/>
<result column="last_name" property="lastName"/>
</resultMap>
<sql id="Base_Column_List">
first_name,last_name
</sql>
<select id="findByListPage" parameterType="com.smp.Page" resultType="com.smp.PageData" useCache="false">
select
<include refid="Base_Column_List"/>
from custom
<where>
<if test="pd.firstName != null and pd.firstName != ''">
and first_name = #{pd.firstName}
</if>
<if test="pd.lastName != null and pd.lastName != ''">
and last_name = #{pd.lastName}
</if>
</where>
</select>
</mapper>
数据库sql脚本,建表及测试数据
if exists (select 1
from sysobjects
where id = object_id('custom')
and type = 'U')
drop table custom
go
/*==============================================================*/
/* Table: t_rule_prepaid_card */
/*==============================================================*/
create table custom (
first_name varchar(100) null,
last_name varchar(100) null,
)
go
INSERT INTO custom (first_name, last_name) VALUES ('1', '1') go
INSERT INTO custom (first_name, last_name) VALUES ('2', '2') go
INSERT INTO custom (first_name, last_name) VALUES ('3', '3') go
INSERT INTO custom (first_name, last_name) VALUES ('4', '4') go
INSERT INTO custom (first_name, last_name) VALUES ('5', '5') go
INSERT INTO custom (first_name, last_name) VALUES ('6', '6') go
INSERT INTO custom (first_name, last_name) VALUES ('7', '7') go
INSERT INTO custom (first_name, last_name) VALUES ('8', '8') go
INSERT INTO custom (first_name, last_name) VALUES ('9', '8') go
INSERT INTO custom (first_name, last_name) VALUES ('10', '10') go
INSERT INTO custom (first_name, last_name) VALUES ('11', '11') go
INSERT INTO custom (first_name, last_name) VALUES ('12', '12') go
INSERT INTO custom (first_name, last_name) VALUES ('13', '13') go
第四步:运行环境进行测试
将改工程部署到tomcat上,运行测试
访问地址:http://localhost:8080/page 查看到控制台打印的信息
一页条数:5
本页内容:[{firstName=6, lastName=6}, {firstName=7, lastName=7}, {firstName=8, lastName=8}, {firstName=9, lastName=8}, {firstName=10, lastName=10}]
总记录数:13
可以根据自己的测试需要调整当前页和每页的条数(此处为了测试方便使用直接赋值方式,可以根据自己的需要改成变量赋值)
最后
有什么疑问可以在评论里留言
源码地址:https://github.com/ssp1523/sybase-mybatis-pagination