参考来自:

1.需求说明

在上篇关于mybatis的pageHelper的使用中,讲述了基本使用。

现在的使用场景为:有一个web页面,需要用来测试数据库的连接信息,而数据库的类型是可选的。

页面示例如下:

所以原本的使用方式已经不再试用。因为需要根据不同的数据库来生成对应的分页语句。当然很多数据库对于通用的分页语句是支持的,但是为了考虑以后的拓展,以防有特殊语法的数据库出现(比如自定义的数据库),还是采用根据数据库类型来决定分页语句。

2.实际使用

2.1 旧代码和旧配置

2017.12.14 Mybatis物理分页插件PageHelper的使用

2.2 新代码和新配置

(1)pom.xml

注意:mybatis的pageHelper插件5.x和4.x差别较大,这里使用的是4.x版本。

         <dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.0</version>
</dependency>
(2)SqlMapConfig.xml

这里和之前的区别就是不再指明dialect。

 <?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>
<plugins>
<!-- com.github.pagehelper为PageHelper类所在包名 -->
<!--<plugin interceptor="com.github.pagehelper.PageHelper">-->
<plugin interceptor="com.baosight.ccs.PageHelper.CCSPageHelper">
<property name="autoRuntimeDialect" value="true"/>
<!--<property name="dialect" value="postgresql"/>-->
<!--设置为true时,使用rowbounds的时候,会将rowbonds的第一个参数offset当做pageNum使用,和startpage中的pageNum效果一样-->
<!--<property name="offsetAsPageNum" value="true"/>-->
<!--设置为true时,使用rowbounds分页时就会进行count查询-->
<property name="rowBoundsWithCount" value="true"/>
<!--设置为true时,如果pagesize=0或者rowbounds.limit=0就会查询出所有的结果-->
<property name="pageSizeZero" value="true"/>
<property name="reasonable" value="true"/>
</plugin>
</plugins>
</configuration>
(3)pageHelper的源码解析

对pageHelper的源码学习后发现,在配置文件中不指明dialect,它的确会自动识别数据库类型,然后生成对应的分页语句。但是它只会生成一次,即如果第一次是postgresql,第二次是mysql,它会一直沿用postgresql(第一次生成sqlUtil后会放入sqlUtilMap,后面都会从map中取)。

pageHelper的源码参考来自:http://blog.csdn.net/u014082617/article/details/71215539

 PageHelper
SqlUtil
PageSqlSource
PostgreSQLParser

这和我的需求不一致。我需要为每个可能出现的数据库类型都生成一个sqlUtil,每种类型都只生成一次,并且放入sqlUtilMap中。因此将配置文件中的参数autoRuntimeDialect设为true。

(4)pageHelper的重写

这里有一个奇怪的问题:并没有生效。因此重写pageHelper的代码,在代码中将变量autoRuntimeDialect设置为true,而后生效

 package com.baosight.ccs.PageHelper;

 import com.baosight.common.utils.StringUtils; import com.github.pagehelper.PageHelper;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 自定义的分页拦截器,支持通用的数据库和自定义的sts数据库
*/
@SuppressWarnings("rawtypes")
@Intercepts(@Signature(type = Executor.class, method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}))
public class CCSPageHelper extends PageHelper {
//sql工具类
private SqlUtil sqlUtil;
//属性参数信息
private Properties properties;
//配置对象方式
private SqlUtilConfig sqlUtilConfig;
//自动获取dialect,如果没有setProperties或setSqlUtilConfig,也可以正常进行
private boolean autoDialect = true;
//运行时自动获取dialect
private boolean autoRuntimeDialect = true;

但是运行后出现了另一问题:操作几次页面之后,连接超出最大数,连接失败。

 Caused by: org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.RuntimeException: com.alibaba.druid.pool.GetConnectionTimeoutException:
wait millis 10000, active 15, maxActive 15

查看pageHelper的源码发现,本来只执行一次的getSqlUtil,因为authRuntimeDialect=true,将会每次都去执行,如果有则从map中取,否则创建一个。

而为了拿到url而获取的连接并没有及时关闭,导致连接被多次创建,直到超过最大连接数。因此重写pageHelper。

 package com.baosight.ccs.PageHelper;

 //import com.github.pagehelper.Dialect;
import com.baosight.common.utils.StringUtils;
import com.baosight.xinsight.dbs.datasource.MultiDataSource;
import com.github.pagehelper.Dialect;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.SqlUtil;
import com.github.pagehelper.SqlUtilConfig;
import com.github.pagehelper.StringUtil; import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock; import javax.sql.DataSource; /**
* 自定义的分页拦截器,支持通用的数据库和自定义的sts数据库
*/
@SuppressWarnings("rawtypes")
@Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}))
public class CCSPageHelper extends PageHelper {
//sql工具类
private SqlUtil sqlUtil;
//属性参数信息
private Properties properties;
//配置对象方式
private SqlUtilConfig sqlUtilConfig;
//自动获取dialect,如果没有setProperties或setSqlUtilConfig,也可以正常进行
private boolean autoDialect = true;
//运行时自动获取dialect
private boolean autoRuntimeDialect = true;
//缓存
private Map<String, SqlUtil> urlSqlUtilMap = new ConcurrentHashMap<String, SqlUtil>(); private int count = 0;
private static final Logger logger = LoggerFactory.getLogger(CCSPageHelper.class); @Override
public SqlUtil getSqlUtil(Invocation invocation) {
MappedStatement ms = (MappedStatement) invocation.getArgs()[0]; String url = null;
Connection cn = null;
try {
DataSource dataSource = ms.getConfiguration().getEnvironment().getDataSource();
cn = dataSource.getConnection();
url = cn.getMetaData().getURL();
} catch (SQLException e) {
   throw new RuntimeException(e1);130 }finally {
131 try {
132 cn.close();
133 } catch (SQLException e) {
134 throw new RuntimeException(e);
135 }
136 }

//其余和pageHelper一样 }
}

原本代码是没有关闭connection的:

         String url;
DataSource dataSource = ms.getConfiguration().getEnvironment().getDataSource();
try {
url = dataSource.getConnection().getMetaData().getURL();
} catch (SQLException e) {
throw new RuntimeException(e);
}

至此需求完成。

2017.12.25 Mybatis物理分页插件PageHelper的使用(二)的更多相关文章

  1. 2017.12.14 Mybatis物理分页插件PageHelper的使用(一)

    参考来自: http://www.360doc.com/content/15/0728/15/12642656_487954693.shtml https://www.cnblogs.com/digd ...

  2. Mybatis分页插件PageHelper的配置和使用方法

     Mybatis分页插件PageHelper的配置和使用方法 前言 在web开发过程中涉及到表格时,例如dataTable,就会产生分页的需求,通常我们将分页方式分为两种:前端分页和后端分页. 前端分 ...

  3. Java SSM框架之MyBatis3(三)Mybatis分页插件PageHelper

    引言 对于使用Mybatis时,最头痛的就是写分页,需要先写一个查询count的select语句,然后再写一个真正分页查询的语句,当查询条件多了之后,会发现真不想花双倍的时间写count和select ...

  4. Mybatis框架插件PageHelper的使用

    在web开发过程中涉及到表格时,例如dataTable,就会产生分页的需求,通常我们将分页方式分为两种:前端分页和后端分页. 前端分页 一次性请求数据表格中的所有记录(ajax),然后在前端缓存并且计 ...

  5. Mybatis学习---Mybatis分页插件 - PageHelper

    1. Mybatis分页插件 - PageHelper说明 如果你也在用Mybatis,建议尝试该分页插件,这个一定是最方便使用的分页插件. 该插件目前支持Oracle,Mysql,MariaDB,S ...

  6. Mybatis分页插件PageHelper的实现

    Mybatis分页插件PageHelper的实现 前言 分页这个概念在做web网站的时候很多都会碰到 说它简单吧 其实也简单 小型的网站,完全可以自己写一个,首先查出数据库总条数,然后按照分页大小分为 ...

  7. Mybatis分页插件PageHelper使用

    一. Mybatis分页插件PageHelper使用  1.不使用插件如何分页: 使用mybatis实现: 1)接口: List<Student> selectStudent(Map< ...

  8. 基于Mybatis分页插件PageHelper

    基于Mybatis分页插件PageHelper 1.分页插件使用 1.POM依赖 PageHelper的依赖如下.需要新的版本可以去maven上自行选择 <!-- PageHelper 插件分页 ...

  9. Mybatis分页插件-PageHelper的使用

    转载:http://blog.csdn.net/u012728960/article/details/50791343 Mybatis分页插件-PageHelper的使用 怎样配置mybatis这里就 ...

随机推荐

  1. Druid数据迁移小计

    Druid数据迁移小计 Druid 官方网站上讲了相关的 Dump Segment 和 Insert Segment 相关的功能,但是经过测试这些功能都不好用,报 Guice 的依赖错误,懒得找具体原 ...

  2. 堆管理之malloc和free分析

    在win7 64环境下分析 1.malloc代码 int main(){ void *p = malloc(0xa8); memset(p, 'a', 0xa8); free(p); return 0 ...

  3. Web框架以及两种模式MVC,MTV

    一.Web框架的本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. import socket def handle_reques ...

  4. Quartz.NET 3.0.7 + MySql 动态调度作业+动态切换版本+多作业引用同一程序集不同版本+持久化+集群(四)

    把 HAProxy 用上了,终于不用担心某个节点挂了,还要去手动修改管理后台配置文件的api地址了. 在某网站下载了一个 window 可以用的版本 haproxy-1.7.8 不得不吐槽一下,作者要 ...

  5. WAR/EAR 概念

    In J2EE application, modules are packaged as EAR, JAR and WAR based on their functionality JAR: EJB ...

  6. 【BZOJ 3994】3994: [SDOI2015]约数个数和(莫比乌斯反演)

    3994: [SDOI2015]约数个数和 Description  设d(x)为x的约数个数,给定N.M,求   Input 输入文件包含多组测试数据. 第一行,一个整数T,表示测试数据的组数. 接 ...

  7. hdu 4071& poj 3873 & zoj 3386 & uva 12197 Trick or Treat 三分法

    思路: 看到这个题目就发现所需最短时间也就是房子和相遇点的最远距离具有凹凸性,很容易就想到了三分法枚举. 找出所有房子的X坐标的最小最大值作为上下界. 代码如下: #include<stdio. ...

  8. strust2的核心和工作原理

    在学习strust2之前,我们要明白使用struts2的目的是什么?它能给我们带来什么样的好处? 设计目标 Strust设计的第一目标就是使MVC模式应用于web程序设计. 技术优势 Struts2有 ...

  9. 1.3(SQL学习笔记)计算字段及函数

    一.计算字段 1.1拼接字段 一般情况下返回的字段是指定列的属性名.如果有时我们对返回格式有特殊要求. 例如,我们需要将显示商品名,即商品价格,同时商品名后面的价格放在括号内. prod_name(p ...

  10. matlab2016b ubuntu命令行安装 + matconvnet的安装

    0. 下载安装包 下载的文件有Matlab 2016b Linux64 Crack.rar,R2016b_glnxa64_dvd2.iso,R2016b_glnxa64_dvd1.iso. 1. 拷贝 ...