文档章节

dobbo下mybatis PageList 分页信息丢失问题解决

heyJude
 heyJude
发布于 2016/05/16 17:28
字数 601
阅读 76
收藏 0

在使用mybatis 分页插件mybatis-paginator 时,返回的结果保存在PageList 对象中

public class PageList<E> extends ArrayList<E> implements Serializable {

    private Paginator paginator;
    
    ...
}

paginator 保存了此次查询的分页信息 因为PageList继承了ArrayList dobbo 在序列化 PageList 对象的时候用CollectionSerializer

 if (Collection.class.isAssignableFrom(cl)) {
      if (_collectionSerializer == null) {
	_collectionSerializer = new CollectionSerializer();
      }

      serializer = _collectionSerializer;
    }

我们看CollectionSerializer 的 writeObject(Object obj, AbstractHessianOutput out) 方法

public void writeObject(Object obj, AbstractHessianOutput out)
    throws IOException
  {
    if (out.addRef(obj))
      return;

    Collection list = (Collection) obj;

    Class cl = obj.getClass();
    boolean hasEnd;
    
    if (cl.equals(ArrayList.class)
	|| ! _sendJavaType
	|| ! Serializable.class.isAssignableFrom(cl))
      hasEnd = out.writeListBegin(list.size(), null);
    else
      hasEnd = out.writeListBegin(list.size(), obj.getClass().getName());

    Iterator iter = list.iterator();
    while (iter.hasNext()) {
      Object value = iter.next();

      out.writeObject(value);
    }

    if (hasEnd)
      out.writeListEnd();
  }

注意下面的代码,写入stream 的只有list存放的数据,PageList 的参数 Paginator 被忽略掉了

    Iterator iter = list.iterator();
    while (iter.hasNext()) {
      Object value = iter.next();

      out.writeObject(value);
    }

就这样Paginator 丢失了。

解决: 序列化 查看com.alibaba.com.caucho.hessian.io.SerializerFactory 的源码 发现 方法 Serializer getSerializer(Class cl); 支持 writeReplace

 else if (JavaSerializer.getWriteReplace(cl) != null)
      serializer = new JavaSerializer(cl, _loader);

新增转换类SerializerList:

package com.alibaba.dubbo.common.serialize.serialization.page;

import com.alibaba.com.caucho.hessian.io.HessianHandle;

import java.io.ObjectStreamException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class SerializerList<E>
        implements HessianHandle ,Serializable{

    private List<E> data;
    
    private static final long serialVersionUID = -1;

    public SerializerList(Collection<? extends E> c) {
        if (c == null)
            data = new ArrayList<E>();
        else
            data = new ArrayList<E>(c);
    }

    public SerializerList() {
        data = new ArrayList<E>();
    }

    public List<E> getData() {
        return data;
    }

    public void setData(List<E> data) {
        this.data = data;
    }

    private Object readResolve() throws ObjectStreamException{
        PageList list = new PageList(data);
        if (data.size() > 0) {
            if (data.get(0) instanceof Paginator) {
                Object o = data.get(0);
                data.remove(0);
                return new PageList(data, (Paginator) o);
            }
        }
        return new PageList(data);
    }
}

修改PageList 新增一个writeReplace()方法,代码如下

    /**
     * 创建新的序列化对象,并放入分页信息
     */
    private Object writeReplace() throws ObjectStreamException{
        SerializerList list = new SerializerList(this);
        if(paginator!=null)
            list.getData().add(0,paginator);
        return list;
    }

这样写入stream 的就是SerializerList 了,分页信息成功写入。 反序列化: com.alibaba.com.caucho.hessian.io.JavaDeserializer 是支持readResolve 的

  protected Method getReadResolve(Class cl)
  {
    for (; cl != null; cl = cl.getSuperclass()) {
      Method []methods = cl.getDeclaredMethods();
      
      for (int i = 0; i < methods.length; i++) {
	Method method = methods[i];

	if (method.getName().equals("readResolve") &&
	    method.getParameterTypes().length == 0)
	  return method;
      }
    }

    return null;
  }

查看com.alibaba.com.caucho.hessian.io.SerializerFactory 的源码 方法 Deserializer getObjectDeserializer(String type, Class cl) type 是我们之前序列化时写入的类型SerializerList
class PageList 是反序列化最终获取的类型

public Deserializer getObjectDeserializer(String type, Class cl)
    throws HessianProtocolException
  {
    Deserializer reader = getObjectDeserializer(type);
    
    if (cl == null
	|| cl.equals(reader.getType())
	|| cl.isAssignableFrom(reader.getType())
	|| HessianHandle.class.isAssignableFrom(reader.getType())) {
      return reader;
    }

    if (log.isLoggable(Level.FINE)) {
      log.fine("hessian: expected '" + cl.getName() + "' at '" + type + "' ("
	       + reader.getType().getName() + ")");
    }
    
    return getDeserializer(cl);
  }

注意 HessianHandle.class.isAssignableFrom(reader.getType()) HessianHandle 是一个接口,没有方法,SerializerList 需要实现HessianHandle 还有对应的readResolve()

    private Object readResolve() throws ObjectStreamException{
        PageList list = new PageList(data);
        if (data.size() > 0) {
            if (data.get(0) instanceof Paginator) {
                Object o = data.get(0);
                data.remove(0);
                return new PageList(data, (Paginator) o);
            }
        }
        return new PageList(data);
    }

问题解决!

© 著作权归作者所有

共有 人打赏支持
下一篇: 禅道
heyJude
粉丝 1
博文 11
码字总数 1836
作品 0
崇明
私信 提问
Mybatis分页和Spring的集成

写了一个Mybatis分页控件,在这记录一下使用方式。 在Maven中加入依赖: <dependencies> ... <dependency> <groupId>com.github.miemiedev</groupId> <artifactId>mybatis-paginator</artif......

miemiedev
2013/06/04
0
108
Mybatis Paginator分页

mybatis-paginator是gethub上的一个开源项目、用于java后台获取分页数据、该开源项目还提供一个列表组件(mmgrid)用于前端展示。 该开源项目地址:https://github.com/miemiedev 参考博客:...

_Roger_
2015/10/20
103
0
Mybatis3.3.x技术内幕(十三):Mybatis之RowBounds分页原理

Mybatis可以通过传递RowBounds对象,来进行数据库数据的分页操作,然而遗憾的是,该分页操作是对ResultSet结果集进行分页,也就是人们常说的逻辑分页,而非物理分页。 RowBounds对象的源码如...

祖大俊
2016/05/08
2.5K
2
Easyui页面分页问题

在使用easyui的分页功能时,设置的pageList为[20,30,40,50],代码如下: 当pageList为[20,30,40,50]的时候是没有任何问题的,但是当我把pageList[50,100,150,200]的时候却出现了问题,当pageS...

影非弦
2015/08/11
638
1
SSE+easyui 分页

记录过程 1、dom添加分页支持 com.github.miemiedevmybatis-paginator 2、mybatis.xml 配置分页 3、mybatis的maper和xml文件对应,配置位置spring.xml 4、开始写js代码 $entity = getQueryDa...

卯金刀GG
2016/09/22
20
0

没有更多内容

加载失败,请刷新页面

加载更多

java框架学习日志-13(Mybatis基本概念和简单的例子)

在mybatis初次学习Mybatis的时候,遇到了很多问题,虽然阿里云的视频有教学,但是视频教学所使用的软件和我自己使用的软件不用,我自己用的数据库是oracle数据库,开发环境是idea。而且视频中...

白话
24分钟前
1
0
Java基础:String、StringBuffer和StringBuilder的区别

1 String String:字符串常量,字符串长度不可变。Java中String是immutable(不可变)的。 String类的包含如下定义: /** The value is used for character storage. */private final cha...

watermelon11
50分钟前
2
0
mogodb服务

部署MongoDB 官网: https://www.mongodb.com/download-center/community 创建mongo数据目录 mkdir /data/mongodb 二进制部署 wget -c https://fastdl.mongodb.org/linux/mongodb-linux-x8......

以谁为师
昨天
5
0
大神教你Debian GNU/Linux 9.7 “Stretch” Live和安装镜像开放下载

Debian项目团队于昨天发布了Debian GNU/Linux 9 "Stretch" 的第7个维护版本更新,重点修复了APT软件管理器中存在的安全漏洞。在敦促每位用户尽快升级系统的同时,Debian团队还发布了Debian ...

linux-tao
昨天
4
0
PHP 相关配置

1. php-fpm的pool 编辑php-fpm配置文件php-fpm.con vim /usr/local/php/etc/php-fpm.conf //在[global]部分增加以下内容 include = etc/php-fpm.d/*.conf # 相当与Nginx的虚拟主机文件 “vho......

Yue_Chen
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部