2012年5月

Java的BeanUtils.copyProperties与PropertyUtils.copyProperties用法及区别

一、简介:

BeanUtils提供对Java反射和自省API的包装。其主要目的是利用反射机制对JavaBean的属性进行处理。我们知道,一个JavaBean通常包含了大量的属性,很多情况下,对JavaBean的处理导致大量get/set代码堆积,增加了代码长度和阅读代码的难度。

二、用法:

BeanUtils是这个包里比较常用的一个工具类,这里只介绍它的copyProperties()方法。该方法定义如下:

public static void copyProperties(java.lang.Object dest,java.lang.Object orig)
throws java.lang.IllegalAccessException,
java.lang.reflect.InvocationTargetException

如果你有两个具有很多相同属性的JavaBean,一个很常见的情况就是Struts里的PO对象(持久对象)和对应的ActionForm,例如 Teacher和TeacherForm。我们一般会在Action里从ActionForm构造一个PO对象,传统的方式是使用类似下面的语句对属性逐个赋值:

//得到TeacherForm
TeacherForm teacherForm=(TeacherForm)form;
//构造Teacher对象
Teacher teacher=new Teacher();
//赋值
teacher.setName(teacherForm.getName());
teacher.setAge(teacherForm.getAge());
teacher.setGender(teacherForm.getGender());
teacher.setMajor(teacherForm.getMajor());
teacher.setDepartment(teacherForm.getDepartment());

//持久化Teacher对象到数据库
HibernateDAO.save(teacher);

而使用BeanUtils后,代码就大大改观了,如下所示:
//得到TeacherForm
TeacherForm teacherForm=(TeacherForm)form;
//构造Teacher对象
Teacher teacher=new Teacher();
//赋值
BeanUtils.copyProperties(teacher,teacherForm);
//持久化Teacher对象到数据库
HibernateDAO.save(teacher);

如果Teacher和TeacherForm间存在名称不相同的属性,则BeanUtils不对这些属性进行处理,需要程序员手动处理。例如 Teacher包含modifyDate(该属性记录最后修改日期,不需要用户在界面中输入)属性而TeacherForm无此属性,那么在上面代码的 copyProperties()后还要加上一句:

teacher.setModifyDate(new Date());

怎么样,很方便吧!除BeanUtils外还有一个名为PropertyUtils的工具类,它也提供copyProperties()方法,作用与 BeanUtils的同名方法十分相似,主要的区别在于后者提供类型转换功能,即发现两个JavaBean的同名属性为不同类型时,在支持的数据类型范围内进行转换,而前者不支持这个功能,但是速度会更快一些。BeanUtils支持的转换类型如下:

* java.lang.BigDecimal
* java.lang.BigInteger
* boolean and java.lang.Boolean
* byte and java.lang.Byte
* char and java.lang.Character
* java.lang.Class
* double and java.lang.Double
* float and java.lang.Float
* int and java.lang.Integer
* long and java.lang.Long
* short and java.lang.Short
* java.lang.String
* java.sql.Date
* java.sql.Time
* java.sql.Timestamp

这里要注意一点,java.util.Date是不被支持的,而它的子类java.sql.Date是被支持的。因此如果对象包含时间类型的属性,且希望被转换的时候,一定要使用java.sql.Date类型。否则在转换时会提示argument mistype异常。

三、优缺点:

Apache Jakarta Commons项目非常有用。我曾在许多不同的项目上或直接或间接地使用各种流行的commons组件。其中的一个强大的组件就是BeanUtils。我 将说明如何使用BeanUtils将local实体bean转换为对应的value 对象:

BeanUtils.copyProperties(aValue, aLocal)

上面的代码从aLocal对象复制属性到aValue对象。它相当简单!它不管local(或对应的value)对象有多少个属性,只管进行复制。我们假设 local对象有100个属性。上面的代码使我们可以无需键入至少100行的冗长、容易出错和反复的get和set方法调用。这太棒了!太强大了!太有用 了!

现在,还有一个坏消息:使用BeanUtils的成本惊人地昂贵!我做了一个简单的测试,BeanUtils所花费的时间要超过取数 据、将其复制到对应的 value对象(通过手动调用get和set方法),以及通过串行化将其返回到远程的客户机的时间总和。所以要小心使用这种威力!

Java中Hibernate框架持久化对象的生命周期详解

在Java开发中,Hibernate中持久化对象在被操作过程中可以分为三个阶段,这三个阶段是和Session的周期相关的,因为Hibernate中的操作都是基于Session完成的。所以Session对象的生命周期也关系着持久化对象的生命周期。
持久化对象的生命周期有三种,分别是瞬时态(Transient),持久态(Persistent)和脱管态(Detached)。
瞬时态的对象是刚刚用new关键字创建出来的,还没有进入Session,此时的对象没有和数据库中的记录对应。示例代码如下:

Java代码 

 收藏代码

  1. User user = new User();
  2. user.setName("Sarin");
  3. user.setCity("大连");
  4. user.setDepartment("研发部");
  5. user.setPhone("15912345678");
  6. user.setHireTime(new java.util.Date());

这时user就是出于瞬时态的持久化对象。
通过Session对象的save(),persist()或者saveOrUpdate()方法进行保存处于瞬时态的对象后,该对象就变为持久态。此时Session中已经存在该对象,并且对应数据库中的一条记录。值得注意的是在Session对象失效之前,对持久态对象的任何修改,在调用Session对象的close()方法或者Transaction对象的commit()方法之后,数据库表中对应的数据会同时更新。示例代码如下:

Java代码 

 收藏代码

  1. SessionFactory sessionFactory = config.buildSessionFactory();
  2. Session session = sessionFactory.getCurrentSession();
  3. Transaction tx = session.beginTransaction();
  4. User user = new User();
  5. user.setName("Sarin");
  6. user.setCity("大连");
  7. user.setDepartment("研发部");
  8. user.setPhone("15912345678");
  9. user.setHireTime(new java.util.Date());
  10. session.save(user);
  11. tx.commit();

在调用save()方法后,持久化对象user就变为持久态,但是执行了commit()方法之后,数据库操作才会进行,这点必须明确。所以在数据库操作执行之前对持久化对象的修改Hibernate可以感知。
而且Session对象的get()和load()方法也可以返回一个持久态的对象,这个对象代表数据库表中的一条记录。
脱管态,这个要格外注意,不是托管态,是离开Session管理的状态。处于脱管态的持久化对象的标识符属性和数据库表中某条记录的主键对应,但是它脱离了Session的管理,再次对其操作时,Hibernate无法感知其变化。如下示例:

Java代码 

 收藏代码

  1. SessionFactory sessionFactory = config.buildSessionFactory();
  2. Session session = sessionFactory.getCurrentSession();
  3. Transaction tx = session.beginTransaction();
  4. User user = new User();
  5. user.setName("Sarin");
  6. user.setCity("大连");
  7. user.setDepartment("研发部");
  8. user.setPhone("15912345678");
  9. user.setHireTime(new java.util.Date());
  10. session.save(user);
  11. tx.commit();
  12. user.setCity("北京");

虽然后来又修改了user对象的city属性,但是是在脱管态修改的,程序结束也不能再影响数据库中数据变化。处于脱管态的对象可以重新调用Session对象的update()方法回到持久态,否则Java虚拟机会在适当时间进行垃圾收集。重新持久化对象的过程如下:

Java代码 

 收藏代码

  1. SessionFactory sessionFactory = config.buildSessionFactory();
  2.     Session session = sessionFactory.getCurrentSession();
  3.     Transaction tx = session.beginTransaction();
  4.     User user = new User();
  5.     user.setName("Sarin");
  6.     user.setCity("大连");
  7.     user.setDepartment("研发部");
  8.     user.setPhone("15912345678");
  9.     user.setHireTime(new java.util.Date());
  10.     session.save(user);
  11.     tx.commit();
  12.     user.setCity("北京");
  13.     session = sessionFactory.getCurrentSession();
  14.     tx = session.beginTransaction();
  15.     session.update(user);
  16.     tx.commit();

当使用Session对象的delete()方法删除数据后,处于持久态的对象失去和数据库数据的对应关系,此时的持久化对象将在适当时间被Java虚拟机进行垃圾收集。

Java代码 

 收藏代码

  1. SessionFactory sessionFactory = config.buildSessionFactory();
  2. Session session = sessionFactory.getCurrentSession();
  3. Transaction tx = session.beginTransaction();
  4. User user = (User) session.get(User.class, new Integer(1));
  5. session.delete(user);
  6. tx.commit();

至此Hibernate中持久化对象的三种状态介绍完了。我们会发现处于瞬时态和脱管态的对象不在Hibernate的Session管理中,这时无论怎样修改对象的属性都不会影响数据库中的数据。而处于持久态的对象在Session对象执行close()方法或Transaction对象执行commit()方法时,数据库中数据会同步更新,这也是Hibernate对对象的“脏”数据进行检查的一种方式。
本文系作者的个人理解,欢迎交流。

 

原文:http://sarin.iteye.com/blog/701398

web开发中ajax的get和post两种请求方式的区别

Ajax中我们经常用到get和post请求.那么什么时候用get请求,什么时候用post方式请求呢? 在做回答前我们首先要了解get和post的区别.

1、 get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。post是通过HTTP post机制,将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。

2、 对于get方式,服务器端用Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。两种方式的参数都可以用Request来获得。

3、get传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,因服务器的不同而异.

4、get安全性非常低,post安全性较高。

5、 <form method="get" action="a.asp?b=b">跟<form method="get" action="a.asp">是一样的,也就是说,method为get时action页面后边带的参数列表会被忽视;而<form method="post" action="a.asp?b=b">跟<form method="post" action="a.asp">是不一样的。

另外
Get请求有如下特性:它会将数据添加到URL中,通过这种方式传递到服务器,通常利用一个问号?代表URL地址的结尾与数据参数的开端,后面的参数每一个数据参数以“名称=值”的形式出现,参数与参数之间利用一个连接符&来区分。
Post请求有如下特性:数据是放在HTTP主体中的,其组织方式不只一种,有&连接方式,也有分割符方式,可隐藏参数,传递大批数据,比较方便。

通过以上的说明,现在我们大致了解了什么时候用get什么时候用post方式了吧,对!当我们在提交表单的时候我们通常用post方式,当我们要传送一个较大的数据文件时,需要用post。当传递的值只需用参数方式(这个值不大于2KB)的时候,用get方式即可。

现在我们再看看通过URL发送请求时,get方式和post方式的区别。用下面的例子可以很容易的看到同样的数据通过GET和POST来发送的区别, 发送的数据是 username=张三 :
GET 方式, 浏览器键入 http://localhost?username=张三


GET /?username=%E5%BC%A0%E4%B8%89 HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)
Host: localhost
Connection: Keep-Alive

POST 方式:

POST / HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*
Accept-Language: zh-cn
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)
Host: localhost
Content-Length: 28
Connection: Keep-Alive

username=%E5%BC%A0%E4%B8%89

区别就是一个在 URL 请求里面附带了表单参数和值, 一个是在 HTTP 请求的消息实体中。

比较一下上面的两段文字, 我们会发现 GET 方式把表单内容放在前面的请求头中, 而 POST 则把这些内容放在请求的主体中了, 同时 POST 中把请求的 Content-Type 头设置为 application/x-www-form-urlencoded. 而发送的正文都是一样的, 可以这样来构造一个表单提交正文:
encodeURIComponent(arg1)=encodeURIComponent(value1)&encodeURIComponent(arg2)=encodeURIComponent(value2)&.....

注: encodeURIComponent 返回一个包含了 charstring 内容的新的 String 对象(Unicode 格式), 所有空格、标点、重音符号以及其他非 ASCII 字符都用 %xx 编码代替,其中 xx 等于表示该字符的十六进制数。 例如,空格返回的是 "%20" 。 字符的值大于 255 的用 %uxxxx 格式存储。参见 JavaScript 的 encodeURIComponent() 方法.

在了解了上面的内容后我们现在用ajax的XMLHttpRequest对象向服务器分别用GET和POST方式发送一些数据。

GET 方式
var postContent ="name=" + encodeURIComponent("xiaocheng") + "&email=" + encodeURIComponent("xiaochengf_21@yahoo.com.cn");
xmlhttp.open("GET", "somepage" + "?" + postContent, true);
xmlhttp.send(null);


POST 方式

var postContent ="name=" + encodeURIComponent("xiaocheng") + "&email=" + encodeURIComponent("xiaochengf_21@yahoo.com.cn");
xmlhttp.open("POST", "somepage", true);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
//xmlhttp.setRequestHeader("Content-Type", "text/xml"); //如果发送的是一个xml文件
xmlhttp.send(postContent);
转自:http://www.javaeye.com/topic/148033

Java 完整实现 PHP 的 serialize(序列化)和unserialize(反序列化) 方法

近期做项目,需要用到遗留的php系统的数据库,里面的某些字段是以对象存储的,所以网站找了下资料。

这个版本目前实现了对各种基本类型、数组、ArrayList、HashMap、和其它可序列化对象的序列化。实现了 PHP 5 中的 Serializable 接口的支持。实现了 PHP 中的 __sleep 和 __wakeup 魔术方法的支持。实现了对所有标示(N、b、i、d、s、a、O、R、r、U、C)的反序列化,在对标示 a 反序列化时,可以根据下标和值来自动判断是 ArrayList 还是 HashMap。并且在反序列化时可以强制指定反序列化的类型。

该类是静态类,无需也不能被实例化。除了包含了 serialize 和 unserialize 方法以外,还增加了一个 cast 方法,用来进行反序列化后的类型转换,该方法主要用于将反序列化后的 ArrayList 转化为数组或者 HashMap。

该类在 J2SE SDK 1.3.1 和更高版本上编译通过,更低版本的未做测试。
实现代码

PHPSerializer.java
/* PHPSerializer.java
 *
 * Author:       Ma Bingyao <andot@ujn.edu.cn>
 * Copyright:    CoolCode.CN
 * Version:      2.1
 * LastModified: 2006-08-09
 * This library is free.  You can redistribute it and/or modify it.
 * http://www.coolcode.cn/?p=202
 */
package org.phprpc.util;
import java.io.*;
import java.util.*;
import java.lang.reflect.*;
class UnSerializeResult {
    public Object value;
    public int hv;
    public UnSerializeResult() {}
    public UnSerializeResult(Object value, int hv) {
        this.value = value;
        this.hv = hv;
    }
}
public class PHPSerializer {
    private static Package[] __packages = Package.getPackages();
    private static final byte __Quote = 34;
    private static final byte __0 = 48;
    private static final byte __1 = 49;
    private static final byte __Colon = 58;
    private static final byte __Semicolon = 59;
    private static final byte __C = 67;
    private static final byte __N = 78;
    private static final byte __O = 79;
    private static final byte __R = 82;
    private static final byte __U = 85;
    private static final byte __Slash = 92;
    private static final byte __a = 97;
    private static final byte __b = 98;
    private static final byte __d = 100;
    private static final byte __i = 105;
    private static final byte __r = 114;
    private static final byte __s = 115;
    private static final byte __LeftB = 123;
    private static final byte __RightB = 125;
    private static final String __NAN = new String("NAN");
    private static final String __INF = new String("INF");
    private static final String __NINF = new String("-INF");
    private PHPSerializer() {}
    public static byte[] serialize(Object obj) {
        return serialize(obj, "UTF-8");
    }
    public static byte[] serialize(Object obj, String charset) {
        HashMap ht = new HashMap();
        int hv = 1;
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        hv = serialize(stream, obj, ht, hv, charset);
        byte[] result = stream.toByteArray();
        try {
            stream.close();
        } catch (Exception e) {}
        return result;
    }
    public static int serialize(ByteArrayOutputStream stream, Object obj, HashMap ht, int hv, String charset) {
        if (obj == null) {
            hv++;
            writeNull(stream);
        } else {
            if (obj instanceof Boolean) {
                hv++;
                writeBoolean(stream, ((Boolean) obj).booleanValue() ? __1 : __0);
            } else if ((obj instanceof Byte) || (obj instanceof Short)
                    || (obj instanceof Integer)) {
                hv++;
                writeInteger(stream, getBytes(obj));
            } else if (obj instanceof Long) {
                hv++;
                writeDouble(stream, getBytes(obj));
            } else if (obj instanceof Float) {
                hv++;
                Float f = (Float) obj;
                if (f.isNaN()) {
                    writeDouble(stream, getBytes(__NAN));
                } else if (f.isInfinite()) {
                    if (f.floatValue() > 0) {
                        writeDouble(stream, getBytes(__INF));
                    } else {
                        writeDouble(stream, getBytes(__NINF));
                    }
                } else {
                    writeDouble(stream, getBytes(f));
                }
            } else if (obj instanceof Double) {
                hv++;
                Double d = (Double) obj;
                if (d.isNaN()) {
                    writeDouble(stream, getBytes(__NAN));
                } else if (d.isInfinite()) {
                    if (d.doubleValue() > 0) {
                        writeDouble(stream, getBytes(__INF));
                    } else {
                        writeDouble(stream, getBytes(__NINF));
                    }
                } else {
                    writeDouble(stream, getBytes(d));
                }
            } else if ((obj instanceof Character) || (obj instanceof String)) {
                hv++;
                writeString(stream, getBytes(obj, charset));
            } else if (obj.getClass().isArray()) {
                if (ht.containsKey(new Integer(obj.hashCode()))) {
                    writePointRef(stream, getBytes(ht.get(new Integer(obj.hashCode()))));
                } else {
                    ht.put(new Integer(obj.hashCode()), new Integer(hv++));
                    hv = writeArray(stream, obj, ht, hv, charset);
                }
            } else if (obj instanceof ArrayList) {
                if (ht.containsKey(new Integer(obj.hashCode()))) {
                    writePointRef(stream, getBytes(ht.get(new Integer(obj.hashCode()))));
                } else {
                    ht.put(new Integer(obj.hashCode()), new Integer(hv++));
                    hv = writeArrayList(stream, (ArrayList) obj, ht, hv, charset);
                }
            } else if (obj instanceof HashMap) {
                if (ht.containsKey(new Integer(obj.hashCode()))) {
                    writePointRef(stream, getBytes(ht.get(new Integer(obj.hashCode()))));
                } else {
                    ht.put(new Integer(obj.hashCode()), new Integer(hv++));
                    hv = writeHashMap(stream, (HashMap) obj, ht, hv, charset);
                }
            } else {
                if (ht.containsKey(new Integer(obj.hashCode()))) {
                    hv++;
                    writeRef(stream, getBytes(ht.get(new Integer(obj.hashCode()))));
                } else {
                    ht.put(new Integer(obj.hashCode()), new Integer(hv++));
                    hv = writeObject(stream, obj, ht, hv, charset);
                }
            }
        }
        return hv;
    }
    private static void writeNull(ByteArrayOutputStream stream) {
        stream.write(__N);
        stream.write(__Semicolon);
    }
    private static void writeRef(ByteArrayOutputStream stream, byte[] r) {
        stream.write(__r);
        stream.write(__Colon);
        stream.write(r, 0, r.length);
        stream.write(__Semicolon);
    }
    private static void writePointRef(ByteArrayOutputStream stream, byte[] p) {
        stream.write(__R);
        stream.write(__Colon);
        stream.write(p, 0, p.length);
        stream.write(__Semicolon);
    }
    private static void writeBoolean(ByteArrayOutputStream stream, byte b) {
        stream.write(__b);
        stream.write(__Colon);
        stream.write(b);
        stream.write(__Semicolon);
    }
    private static void writeInteger(ByteArrayOutputStream stream, byte[] i) {
        stream.write(__i);
        stream.write(__Colon);
        stream.write(i, 0, i.length);
        stream.write(__Semicolon);
    }
    private static void writeDouble(ByteArrayOutputStream stream, byte[] d) {
        stream.write(__d);
        stream.write(__Colon);
        stream.write(d, 0, d.length);
        stream.write(__Semicolon);
    }
    private static void writeString(ByteArrayOutputStream stream, byte[] s) {
        byte[] slen = getBytes(new Integer(s.length));
        stream.write(__s);
        stream.write(__Colon);
        stream.write(slen, 0, slen.length);
        stream.write(__Colon);
        stream.write(__Quote);
        stream.write(s, 0, s.length);
        stream.write(__Quote);
        stream.write(__Semicolon);
    }
    private static int writeArray(ByteArrayOutputStream stream, Object a, HashMap ht, int hv, String charset) {
        int len = Array.getLength(a);
        byte[] alen = getBytes(new Integer(len));
        stream.write(__a);
        stream.write(__Colon);
        stream.write(alen, 0, alen.length);
        stream.write(__Colon);
        stream.write(__LeftB);
        for (int i = 0; i < len; i++) {
            writeInteger(stream, getBytes(new Integer(i)));
            hv = serialize(stream, Array.get(a, i), ht, hv, charset);
        }
        stream.write(__RightB);
        return hv;
    }
    private static int writeArrayList(ByteArrayOutputStream stream, ArrayList a, HashMap ht, int hv, String charset) {
        int len = a.size();
        byte[] alen = getBytes(new Integer(len));
        stream.write(__a);
        stream.write(__Colon);
        stream.write(alen, 0, alen.length);
        stream.write(__Colon);
        stream.write(__LeftB);
        for (int i = 0; i < len; i++) {
            writeInteger(stream, getBytes(new Integer(i)));
            hv = serialize(stream, a.get(i), ht, hv, charset);
        }
        stream.write(__RightB);
        return hv;
    }
    private static int writeHashMap(ByteArrayOutputStream stream, HashMap h, HashMap ht, int hv, String charset) {
        int len = h.size();
        byte[] hlen = getBytes(new Integer(len));
        stream.write(__a);
        stream.write(__Colon);
        stream.write(hlen, 0, hlen.length);
        stream.write(__Colon);
        stream.write(__LeftB);
        for (Iterator keys = h.keySet().iterator(); keys.hasNext();) {
            Object key = keys.next();
            if ((key instanceof Byte) || (key instanceof Short)
                    || (key instanceof Integer)) {
                writeInteger(stream, getBytes(key));
            } else if (key instanceof Boolean) {
                writeInteger(stream, new byte[] { ((Boolean) key).booleanValue() ? __1 : __0 });
            } else {
                writeString(stream, getBytes(key, charset));
            }
            hv = serialize(stream, h.get(key), ht, hv, charset);
        }
        stream.write(__RightB);
        return hv;
    }
    private static int writeObject(ByteArrayOutputStream stream, Object obj, HashMap ht, int hv, String charset) {
        Class cls = obj.getClass();
        if (obj instanceof java.io.Serializable) {
            byte[] className = getBytes(getClassName(cls), charset);
            byte[] classNameLen = getBytes(new Integer(className.length));
            if (obj instanceof org.phprpc.util.Serializable) {
                byte[] cs = ((org.phprpc.util.Serializable) obj).serialize();
                byte[] cslen = getBytes(new Integer(cs.length));
                stream.write(__C);
                stream.write(__Colon);
                stream.write(classNameLen, 0, classNameLen.length);
                stream.write(__Colon);
                stream.write(__Quote);
                stream.write(className, 0, className.length);
                stream.write(__Quote);
                stream.write(__Colon);
                stream.write(cslen, 0, cslen.length);
                stream.write(__Colon);
                stream.write(__LeftB);
                stream.write(cs, 0, cs.length);
                stream.write(__RightB);
            } else {
                Method __sleep;
                try {
                    __sleep = cls.getMethod("__sleep", new Class[0]);
                } catch (Exception e) {
                    __sleep = null;
                }
                int fl = 0;
                Field[] f;
                if (__sleep != null) {
                    String[] fieldNames;
                    try {
                        __sleep.setAccessible(true);
                        fieldNames = (String[]) __sleep.invoke(obj, new Object[0]);
                    } catch (Exception e) {
                        fieldNames = null;
                    }
                    f = getFields(obj, fieldNames);
                } else {
                    f = getFields(obj);
                }
                AccessibleObject.setAccessible(f, true);
                byte[] flen = getBytes(new Integer(f.length));
                stream.write(__O);
                stream.write(__Colon);
                stream.write(classNameLen, 0, classNameLen.length);
                stream.write(__Colon);
                stream.write(__Quote);
                stream.write(className, 0, className.length);
                stream.write(__Quote);
                stream.write(__Colon);
                stream.write(flen, 0, flen.length);
                stream.write(__Colon);
                stream.write(__LeftB);
                for (int i = 0, len = f.length; i < len; i++) {
                    int mod = f[i].getModifiers();
                    if (Modifier.isPublic(mod)) {
                        writeString(stream, getBytes(f[i].getName(), charset));
                    } else if (Modifier.isProtected(mod)) {
                        writeString(stream,
                                getBytes("\0*\0" + f[i].getName(), charset));
                    } else {
                        writeString(stream,
                                getBytes(
                                "\0" + getClassName(f[i].getDeclaringClass())
                                + "\0" + f[i].getName(),
                                charset));
                    }
                    Object o;
                    try {
                        o = f[i].get(obj);
                    } catch (Exception e) {
                        o = null;
                    }
                    hv = serialize(stream, o, ht, hv, charset);
                }
                stream.write(__RightB);
            }
        } else {
            writeNull(stream);
        }
        return hv;
    }
    private static byte[] getBytes(Object obj) {
        try {
            return obj.toString().getBytes("US-ASCII");
        } catch (Exception e) {
            return obj.toString().getBytes();
        }
    }
    private static byte[] getBytes(Object obj, String charset) {
        try {
            return obj.toString().getBytes(charset);
        } catch (Exception e) {
            return obj.toString().getBytes();
        }
    }
    private static String getString(byte[] data, String charset) {
        try {
            return new String(data, charset);
        } catch (Exception e) {
            return new String(data);
        }
    }
    private static Class getClass(String className) {
        try {
            Class cls = Class.forName(className);
            return cls;
        } catch (Exception e) {}
        for (int i = 0; i < __packages.length; i++) {
            try {
                Class cls = Class.forName(
                        __packages[i].getName() + "." + className);
                return cls;
            } catch (Exception e) {}
        }
        return null;
    }
    private static String getClassName(Class cls) {
        return cls.getName().substring(cls.getPackage().getName().length() + 1);
    }
    private static Field getField(Object obj, String fieldName) {
        Class cls = obj.getClass();
        while (cls != null) {
            try {
                Field result = cls.getDeclaredField(fieldName);
                int mod = result.getModifiers();
                if (Modifier.isFinal(mod) || Modifier.isStatic(mod)) {
                    return null;
                }
                return result;
            } catch (Exception e) {}
            cls = cls.getSuperclass();
        }
        return null;
    }
    private static Field[] getFields(Object obj, String[] fieldNames) {
        if (fieldNames == null) {
            return getFields(obj);
        }
        int n = fieldNames.length;
        ArrayList fields = new ArrayList(n);
        for (int i = 0; i < n; i++) {
            Field f = getField(obj, fieldNames[i]);
            if (f != null) {
                fields.add(f);
            }
        }
        return (Field[]) fields.toArray(new Field[0]);
    }
    private static Field[] getFields(Object obj) {
        ArrayList fields = new ArrayList();
        Class cls = obj.getClass();
        while (cls != null) {
            Field[] fs = cls.getDeclaredFields();
            for (int i = 0; i < fs.length; i++) {
                int mod = fs[i].getModifiers();
                if (!Modifier.isFinal(mod) && !Modifier.isStatic(mod)) {
                    fields.add(fs[i]);
                }
            }
            cls = cls.getSuperclass();
        }
        return (Field[]) fields.toArray(new Field[0]);
    }
    public static Object newInstance(Class cls) {
        try {
            Constructor ctor = cls.getConstructor(new Class[0]);
            int mod = ctor.getModifiers();
            if (Modifier.isPublic(mod)) {
                return ctor.newInstance(new Object[0]);
            }
        } catch (Exception e) {}
        try {
            Constructor ctor = cls.getConstructor(new Class[] { Integer.TYPE });
            int mod = ctor.getModifiers();
            if (Modifier.isPublic(mod)) {
                return ctor.newInstance(new Object[] { new Integer(0) });
            }
        } catch (Exception e) {}
        try {
            Constructor ctor = cls.getConstructor(new Class[] { Boolean.TYPE });
            int mod = ctor.getModifiers();
            if (Modifier.isPublic(mod)) {
                return ctor.newInstance(new Object[] { new Boolean(false) });
            }
        } catch (Exception e) {}
        try {
            Constructor ctor = cls.getConstructor(new Class[] { String.class });
            int mod = ctor.getModifiers();
            if (Modifier.isPublic(mod)) {
                return ctor.newInstance(new Object[] { "" });
            }
        } catch (Exception e) {}
        Field[] f = cls.getFields();
        for (int i = 0; i < f.length; i++) {
            if (f[i].getType() == cls && Modifier.isStatic(f[i].getModifiers())) {
                try {
                    return f[i].get(null);
                } catch (Exception e) {}
            }
        }
        Method[] m = cls.getMethods();
        for (int i = 0; i < m.length; i++) {
            if (m[i].getReturnType() == cls
                    && Modifier.isStatic(m[i].getModifiers())) {
                try {
                    return m[i].invoke(null, new Object[0]);
                } catch (Exception e) {}
                try {
                    return m[i].invoke(null, new Object[] { new Integer(0) });
                } catch (Exception e) {}
                try {
                    return m[i].invoke(null, new Object[] { new Boolean(false) });
                } catch (Exception e) {}
                try {
                    return m[i].invoke(null, new Object[] { "" });
                } catch (Exception e) {}
            }
        }
        return null;
    }
    public static Number cast(Number n, Class destClass) {
        if (destClass == Byte.class) {
            return new Byte(n.byteValue());
        }
        if (destClass == Short.class) {
            return new Short(n.shortValue());
        }
        if (destClass == Integer.class) {
            return new Integer(n.intValue());
        }
        if (destClass == Long.class) {
            return new Long(n.longValue());
        }
        if (destClass == Float.class) {
            return new Float(n.floatValue());
        }
        if (destClass == Double.class) {
            return new Double(n.doubleValue());
        }
        return n;
    }
    public static Object cast(Object obj, Class destClass) {
        if (obj == null || destClass == null) {
            return obj;
        } else if (obj.getClass() == destClass) {
            return obj;
        } else if (obj instanceof Number) {
            return cast((Number) obj, destClass);
        } else if ((obj instanceof String) && destClass == Character.class) {
            return new Character(((String)obj).charAt(0));
        } else if ((obj instanceof ArrayList) && destClass.isArray()) {
            return toArray((ArrayList) obj, destClass.getComponentType());
        } else if ((obj instanceof ArrayList) && destClass == HashMap.class) {
            return toHashMap((ArrayList) obj);
        } else {
            return obj;
        }
    }
    private static HashMap toHashMap(ArrayList a) {
        int n = a.size();
        HashMap h = new HashMap(n);
        for (int i = 0; i < n; i++) {
            h.put(new Integer(i), a.get(i));
        }
        return h;
    }
    private static Object toArray(ArrayList obj, Class componentType) {
        int n = obj.size();
        Object a = Array.newInstance(componentType, n);
        for (int i = 0; i < n; i++) {
            Array.set(a, i, cast(obj.get(i), componentType));
        }
        return a;
    }
    private static int getPos(ByteArrayInputStream stream) {
        try {
            Field pos = stream.getClass().getDeclaredField("pos");
            pos.setAccessible(true);
            return pos.getInt(stream);
        } catch (Exception e) {
            return 0;
        }
    }
    private static void setPos(ByteArrayInputStream stream, int p) {
        try {
            Field pos = stream.getClass().getDeclaredField("pos");
            pos.setAccessible(true);
            pos.setInt(stream, p);
        } catch (Exception e) {}
    }
    public static Object unserialize(byte[] ss) throws IllegalAccessException {
        return unserialize(ss, null, "UTF-8");
    }
    public static Object unserialize(byte[] ss, String charset) throws IllegalAccessException {
        return unserialize(ss, null, charset);
    }
    public static Object unserialize(byte[] ss, Class cls) throws IllegalAccessException {
        return unserialize(ss, cls, "UTF-8");
    }
    public static Object unserialize(byte[] ss, Class cls, String charset) throws IllegalAccessException {
        int hv = 1;
        ByteArrayInputStream stream = new ByteArrayInputStream(ss);
        Object result = unserialize(stream, new HashMap(), hv, new HashMap(), charset).value;
        try {
            stream.close();
        } catch (Exception e) {}
        return cast(result, cls);
    }
    private static UnSerializeResult unserialize(ByteArrayInputStream stream, HashMap ht, int hv, HashMap rt, String charset) throwsIllegalAccessException {
        Object obj;
        switch (stream.read()) {
        case __N:
            obj = readNull(stream);
            ht.put(new Integer(hv++), obj);
            return new UnSerializeResult(obj, hv);
        case __b:
            obj = readBoolean(stream);
            ht.put(new Integer(hv++), obj);
            return new UnSerializeResult(obj, hv);
        case __i:
            obj = readInteger(stream);
            ht.put(new Integer(hv++), obj);
            return new UnSerializeResult(obj, hv);
        case __d:
            obj = readDouble(stream);
            ht.put(new Integer(hv++), obj);
            return new UnSerializeResult(obj, hv);
        case __s:
            obj = readString(stream, charset);
            ht.put(new Integer(hv++), obj);
            return new UnSerializeResult(obj, hv);
        case __U:
            obj = readUnicodeString(stream);
            ht.put(new Integer(hv++), obj);
            return new UnSerializeResult(obj, hv);
        case __r:
            return readRef(stream, ht, hv, rt);
        case __a:
            return readArray(stream, ht, hv, rt, charset);
        case __O:
            return readObject(stream, ht, hv, rt, charset);
        case __C:
            return readCustomObject(stream, ht, hv, charset);
        case __R:
            return readPointRef(stream, ht, hv, rt);
        default:
            return null;
        }
    }
    private static String readNumber(ByteArrayInputStream stream) {
        StringBuffer sb = new StringBuffer();
        int i = stream.read();
        while ((i != __Semicolon) && (i != __Colon)) {
            sb.append((char) i);
            i = stream.read();
        }
        return sb.toString();
    }
    private static Object readNull(ByteArrayInputStream stream) {
        stream.skip(1);
        return null;
    }
    private static Boolean readBoolean(ByteArrayInputStream stream) {
        stream.skip(1);
        Boolean b = new Boolean(stream.read() == __1);
        stream.skip(1);
        return b;
    }
    private static Number readInteger(ByteArrayInputStream stream) {
        stream.skip(1);
        String i = readNumber(stream);
        try {
            return new Byte(i);
        } catch (Exception e1) {
            try {
                return new Short(i);
            } catch (Exception e2) {
                return new Integer(i);
            }
        }
    }
    private static Number readDouble(ByteArrayInputStream stream) {
        stream.skip(1);
        String d = readNumber(stream);
        if (d.equals(__NAN)) {
            return new Double(Double.NaN);
        }
        if (d.equals(__INF)) {
            return new Double(Double.POSITIVE_INFINITY);
        }
        if (d.equals(__NINF)) {
            return new Double(Double.NEGATIVE_INFINITY);
        }
        try {
            return new Long(d);
        } catch (Exception e1) {
            try {
                Float f = new Float(d);
                if (f.isInfinite()) {
                    return new Double(d);
                } else {
                    return f;
                }
            } catch (Exception e2) {
                return new Float(0);
            }
        }
    }
    private static String readString(ByteArrayInputStream stream, String charset) {
        stream.skip(1);
        int len = Integer.parseInt(readNumber(stream));
        stream.skip(1);
        byte[] buf = new byte[len];
        stream.read(buf, 0, len);
        String s = getString(buf, charset);
        stream.skip(2);
        return s;
    }
    private static String readUnicodeString(ByteArrayInputStream stream) {
        stream.skip(1);
        int l = Integer.parseInt(readNumber(stream));
        stream.skip(1);
        StringBuffer sb = new StringBuffer(l);
        int c;
        for (int i = 0; i < l; i++) {
            if ((c = stream.read()) == __Slash) {
                char c1 = (char) stream.read();
                char c2 = (char) stream.read();
                char c3 = (char) stream.read();
                char c4 = (char) stream.read();
                sb.append(
                        (char) (Integer.parseInt(
                                new String(new char[] { c1, c2, c3, c4 }), 16)));
            } else {
                sb.append((char) c);
            }
        }
        stream.skip(2);
        return sb.toString();
    }
    private static UnSerializeResult readRef(ByteArrayInputStream stream, HashMap ht, int hv, HashMap rt) {
        stream.skip(1);
        Integer r = new Integer(readNumber(stream));
        if (rt.containsKey(r)) {
            rt.put(r, new Boolean(true));
        }
        Object obj = ht.get(r);
        ht.put(new Integer(hv++), obj);
        return new UnSerializeResult(obj, hv);
    }
    private static UnSerializeResult readPointRef(ByteArrayInputStream stream, HashMap ht, int hv, HashMap rt) {
        stream.skip(1);
        Integer r = new Integer(readNumber(stream));
        if (rt.containsKey(r)) {
            rt.put(r, new Boolean(true));
        }
        Object obj = ht.get(r);
        return new UnSerializeResult(obj, hv);
    }
    private static UnSerializeResult readArray(ByteArrayInputStream stream, HashMap ht, int hv, HashMap rt, String charset) throwsIllegalAccessException {
        stream.skip(1);
        int n = Integer.parseInt(readNumber(stream));
        stream.skip(1);
        HashMap h = new HashMap(n);
        ArrayList al = new ArrayList(n);
        Integer r = new Integer(hv);
        rt.put(r, new Boolean(false));
        int p = getPos(stream);
        ht.put(new Integer(hv++), h);
        for (int i = 0; i < n; i++) {
            Object key;
            switch (stream.read()) {
            case __i:
                key = cast(readInteger(stream), Integer.class);
                break;
            case __s:
                key = readString(stream, charset);
                break;
            case __U:
                key = readUnicodeString(stream);
                break;
            default:
                return null;
            }
            UnSerializeResult result = unserialize(stream, ht, hv, rt, charset);
            hv = result.hv;
            if (al != null) {
                if ((key instanceof Integer) && (((Integer) key).intValue() == i)) {
                    al.add(result.value);
                } else {
                    al = null;
                }
            }
            h.put(key, result.value);
        }
        if (al != null) {
            ht.put(r, al);
            if (((Boolean) (rt.get(r))).booleanValue()) {
                hv = r.intValue() + 1;
                setPos(stream, p);
                for (int i = 0; i < n; i++) {
                    int key;
                    switch (stream.read()) {
                    case __i:
                        key = ((Integer) cast(readInteger(stream), Integer.class)).intValue();
                        break;
                    default:
                        return null;
                    }
                    UnSerializeResult result = unserialize(stream, ht, hv, rt,
                            charset);
                    hv = result.hv;
                    al.set(key, result.value);
                }
            }
        }
        rt.remove(r);
        stream.skip(1);
        return new UnSerializeResult(ht.get(r), hv);
    }
    private static UnSerializeResult readObject(ByteArrayInputStream stream, HashMap ht, int hv, HashMap rt, String charset) throwsIllegalAccessException {
        stream.skip(1);
        int len = Integer.parseInt(readNumber(stream));
        stream.skip(1);
        byte[] buf = new byte[len];
        stream.read(buf, 0, len);
        String cn = getString(buf, charset);
        stream.skip(2);
        int n = Integer.parseInt(readNumber(stream));
        stream.skip(1);
        Class cls = getClass(cn);
        Object o;
        if (cls != null) {
            if ((o = newInstance(cls)) == null) {
                o = new HashMap(n);
            }
        } else {
            o = new HashMap(n);
        }
        ht.put(new Integer(hv++), o);
        for (int i = 0; i < n; i++) {
            String key;
            switch (stream.read()) {
            case __s:
                key = readString(stream, charset);
                break;
            case __U:
                key = readUnicodeString(stream);
                break;
            default:
                return null;
            }
            if (key.charAt(0) == (char) 0) {
                key = key.substring(key.indexOf("\0", 1) + 1);
            }
            UnSerializeResult result = unserialize(stream, ht, hv, rt, charset);
            hv = result.hv;
            if (o instanceof HashMap) {
                ((HashMap) o).put(key, result.value);
            } else {
                Field f = getField(o, key);
                f.setAccessible(true);
                f.set(o, result.value);
            }
        }
        stream.skip(1);
        Method __wakeup = null;
        try {
            __wakeup = o.getClass().getMethod("__wakeup", new Class[0]);
            __wakeup.invoke(o, new Object[0]);
        } catch (Exception e) {}
        return new UnSerializeResult(o, hv);
    }
    private static UnSerializeResult readCustomObject(ByteArrayInputStream stream, HashMap ht, int hv, String charset) {
        stream.skip(1);
        int len = Integer.parseInt(readNumber(stream));
        stream.skip(1);
        byte[] buf = new byte[len];
        stream.read(buf, 0, len);
        String cn = getString(buf, charset);
        stream.skip(2);
        int n = Integer.parseInt(readNumber(stream));
        stream.skip(1);
        Class cls = getClass(cn);
        Object o;
        if (cls != null) {
            o = newInstance(cls);
        } else {
            o = null;
        }
        ht.put(new Integer(hv++), o);
        if (o == null) {
            stream.skip(n);
        } else if (o instanceof org.phprpc.util.Serializable) {
            byte[] b = new byte[n];
            stream.read(b, 0, n);
            ((org.phprpc.util.Serializable) o).unserialize(b);
        } else {
            stream.skip(n);
        }
        stream.skip(1);
        return new UnSerializeResult(o, hv);
    }
}
/* Serializable.java
*
* Author:       Ma Bingyao <andot@ujn.edu.cn>
* Copyright:    CoolCode.CN
* Version:      2.1
* LastModified: 2006-08-09
* This library is free.  You can redistribute it and/or modify it.
* http://www.coolcode.cn/?p=202
*/
package org.phprpc.util;
interface Serializable {
    byte[] serialize();
    void unserialize(byte[] ss);
}

以上内容摘自:http://coolcode.org/?action=show&id=202

Hibernate3的DetachedCriteria支持详解

Hibernate3支持DetachedCriteria,这是一个非常有意义的特性!我们知道,在常规的Web编程中,有大量的动态条件查询,即用户在网页上面自由选择某些条件,程序根据用户的选择条件,动态生成SQL语句,进行查询。

针对这种需求,对于分层应用程序来说,Web层需要传递一个查询的条件列表给业务层对象,业务层对象获得这个条件列表之后,然后依次取出条件,构造查询语句。这里的一个难点是条件列表用什么来构造?传统上使用Map,但是这种方式缺陷很大,Map可以传递的信息非常有限,只能传递name和value,无法传递究竟要做怎样的条件运算,究竟是大于,小于,like,还是其它的什么,业务层对象必须确切掌握每条entry的隐含条件。因此一旦隐含条件改变,业务层对象的查询构造算法必须相应修改,但是这种查询条件的改变是隐式约定的,而不是程序代码约束的,因此非常容易出错。

DetachedCriteria可以解决这个问题,即在web层,程序员使用DetachedCriteria来构造查询条件,然后将这个DetachedCriteria作为方法调用参数传递给业务层对象。而业务层对象获得DetachedCriteria之后,可以在session范围内直接构造Criteria,进行查询。就此,查询语句的构造完全被搬离到web层实现,而业务层则只负责完成持久化和查询的封装即可,与查询条件构造完全解耦,非常完美!这恐怕也是以前很多企图在web层代码中构造HQL语句的人想实现的梦想吧!

示例代码片段如下:

web层程序构造查询条件:

java代码:

DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Department.class);
detachedCriteria.add(Restrictions.eq("name", "department")).createAlias("employees", "e").add(Restrictions.gt(("e.age"), new Integer(20)));

Department和Employee是一对多关联,查询条件为:

名称是“department”开发部门;
部门里面的雇员年龄大于20岁;

业务层对象使用该条件执行查询:

java代码:

detachedCriteria.getExecutableCriteria(session).list();

最大的意义在于,业务层代码是固定不变的,所有查询条件的构造都在web层完成,业务层只负责在session内执行之。这样代码就可放之四海而皆准,都无须修改了。

然而Spring和Hibernate3的DetachedCriteria有不兼容的问题,因此在Spring环境下面使用Hibernate3需要注意:

Spring的HibernateTemplate提供了Hibernate的完美封装,即通过匿名类实现回调,来保证Session的自动资源管理和事务的管理。其中核心方法是:

java代码:

HibernateTemplate.execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
....
}
}

回调方法提供了session作为参数,有了session,就可以自由的使用Hibernate API编程了。使用了spring的之后,代码修改如下:
  web层代码:

java代码:

DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Department.class);
detachedCriteria.createAlias("employees", "e").add(Restrictions.eq("name", "department")).add(Restrictions.gt(("e.age"), new Integer(20)));
departmentManager.findByCriteria(detachedCriteria);

构造detachedCriteria,作为参数传递给departmentManager

业务层代码使用spring,DepartmentManager的findByCriteria如下:

java代码:

public List findByCriteria(final DetachedCriteria detachedCriteria) {
return (List) getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
return criteria.list();
}
});
}

实际上也就是:

java代码:

Criteria criteria = detachedCriteria.getExecutableCriteria(session);
return criteria.list();

而已

但是该程序代码执行,会抛出强制类型转换异常!

我跟踪了一下spring和Hibernate源代码,原因如下:

spring的HibernateTemplate的execute方法提供的回调接口具有Session作为参数,但是实际上,默认情况下,HibernateTemplate传递给回调接口的session并不是org.hibernate.impl.SessionImpl类,而是SessionImpl类的一个Proxy类。之所以替换成为一个Proxy类,HibernateTemplate的注释说明,Proxy提供了一些额外的功能,包括自动设置Cachable,Transaction的超时时间,Session资源的更积极的关闭等等。

java代码:

private boolean exposeNativeSession = false;
...

execute方法内部:

Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session));

但是遗憾的是,Hibernate的DetachedCriteria的setExecutableCriteria方法却要求将session参数强制转为SessionImpl,但是spring传过来的却是一个Proxy类,因此就报错了。

java代码:

public Criteria getExecutableCriteria(Session session) {
impl.setSession( (SessionImpl) session ); // 要求SessionImpl,Spring传递的是Proxy
return impl;
}

解决方法,禁止Spring的HibernateTemplate传递Proxy类,强制要求它传递真实的SessionImpl类,即给exexute方法增加一个参数,提供参数为true,如下:

java代码:

public List findByCriteria(final DetachedCriteria detachedCriteria) {
return (List) getHibernateTemplate().execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException {
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
return criteria.list();
}
}, true);
}

转自:http://dev.yesky.com/241/2033241.shtml