<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Live in code &#187; hack</title>
	<atom:link href="http://www.agatezone.cn/code/tag/hack/feed" rel="self" type="application/rss+xml" />
	<link>http://www.agatezone.cn/code</link>
	<description>agate&#039;s tech blog</description>
	<lastBuildDate>Tue, 20 Jul 2010 05:35:32 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>修正了 syntaxhighlighter-plus 的样式~</title>
		<link>http://www.agatezone.cn/code/archives/147</link>
		<comments>http://www.agatezone.cn/code/archives/147#comments</comments>
		<pubDate>Mon, 01 Sep 2008 15:09:05 +0000</pubDate>
		<dc:creator>agate</dc:creator>
				<category><![CDATA[程序编码]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[hack]]></category>

		<guid isPermaLink="false">http://www.agatezone.cn/code/archives/147</guid>
		<description><![CDATA[老是觉得 syntaxhighlighter-plus 默认的样式和现在的模板不是很搭配, 就是觉得宽度稍微窄了点~ 就操刀小改了一下这个插件的样式表. 改动如下:

.dp-highlighter {
	/* 修改 */
	width: 640px;
	/* 添加 */
	height: expression(this.scrollHeight &#62; 320 ? &#34;320px&#34; : &#34;auto&#34;);
	max-height: 320px;
	/* 注释 */
	/* overflow: auto; */
}

这样便达到刚好的宽度, 合适的高度. 这里要提及一下从中学了一招~ 就是 IE 不支持 css 的 max-height 属性, 但是支持自家的 expression 表达式! 所以可以如上进行 hack 得到和标准同样的效果! 这个方法学习自 LINK
]]></description>
			<content:encoded><![CDATA[<p>老是觉得 syntaxhighlighter-plus 默认的样式和现在的模板不是很搭配, 就是觉得宽度稍微窄了点~ 就操刀小改了一下这个插件的样式表. 改动如下:</p>
<pre class="brush: css;">
.dp-highlighter {
	/* 修改 */
	width: 640px;
	/* 添加 */
	height: expression(this.scrollHeight &gt; 320 ? &quot;320px&quot; : &quot;auto&quot;);
	max-height: 320px;
	/* 注释 */
	/* overflow: auto; */
}
</pre>
<p>这样便达到刚好的宽度, 合适的高度. 这里要提及一下从中学了一招~ 就是 IE 不支持 css 的 max-height 属性, 但是支持自家的 expression 表达式! 所以可以如上进行 hack 得到和标准同样的效果! 这个方法学习自 <a href="http://perishablepress.com/press/2007/01/16/maximum-and-minimum-height-and-width-in-internet-explorer/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/perishablepress.com/press/2007/01/16/maximum-and-minimum-height-and-width-in-internet-explorer/?referer=');">LINK</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.agatezone.cn/code/archives/147/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HQL查&quot;空值&quot;的问题</title>
		<link>http://www.agatezone.cn/code/archives/50</link>
		<comments>http://www.agatezone.cn/code/archives/50#comments</comments>
		<pubDate>Sun, 06 Apr 2008 08:38:51 +0000</pubDate>
		<dc:creator>agate</dc:creator>
				<category><![CDATA[程序编码]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://www.agatezone.cn/code/?p=50</guid>
		<description><![CDATA[今天郁闷了2个小时，不停地试验，就是没成功……(试验什么呢？)就是这个，用HQL来查出一个List，条件是某个字段为空。
两个领域类：

public class User {
	private String username;
	private Group group;
	// ------------- setter
	// ------------- getter
}
public class Group {
	private String groupName;
	private List&#60;User&#62; users;
	// ------------- setter
	// ------------- getter
}

让你查数据库中所有group为空的（即加入组的）所有用户。

考！我们搞程序的难道这个都不会啊？嘿！你别说……我就他妈地试验了2个小时。不就是一个简单地使用HQL嘛！由于我是用Spring整合了Hibernate，所以就用了Spring的HibernateTemplate来快速开发。
我首先写了：

String hql = &#34;from User as u where u.group=?&#34;;
return getHibernateTemplate().find(hql, null);

好了，多么明白的一句话啊！哈哈……错了(Debug查看返回的List的size为0)~恩……是不是不能用等于号"="来匹配啊？于是我又写了：

String hql = &#34;from User as u where u.group is ?&#34;;
return getHibernateTemplate().find(hql, null);

哈哈！好了！结果……(Debug查看返回的List的size为0)~ 8是吧……是不是要用其他的匹配词啊？于是我再次操刀写了：

String hql = &#34;from User as u where u.group like [...]]]></description>
			<content:encoded><![CDATA[<p>今天郁闷了2个小时，不停地试验，就是没成功……(试验什么呢？)就是这个，用HQL来查出一个List，条件是某个字段为空。</p>
<p>两个领域类：</p>
<pre class="brush: java;">
public class User {
	private String username;
	private Group group;
	// ------------- setter
	// ------------- getter
}
public class Group {
	private String groupName;
	private List&lt;User&gt; users;
	// ------------- setter
	// ------------- getter
}
</pre>
<p>让你查数据库中所有group为空的（即加入组的）所有用户。<br />
<span id="more-50"></span><br />
考！我们搞程序的难道这个都不会啊？嘿！你别说……我就他妈地试验了2个小时。不就是一个简单地使用HQL嘛！由于我是用Spring整合了Hibernate，所以就用了Spring的HibernateTemplate来快速开发。</p>
<p>我首先写了：</p>
<pre class="brush: java;">
String hql = &quot;from User as u where u.group=?&quot;;
return getHibernateTemplate().find(hql, null);
</pre>
<p>好了，多么明白的一句话啊！哈哈……错了(Debug查看返回的List的size为0)~恩……是不是不能用等于号"="来匹配啊？于是我又写了：</p>
<pre class="brush: java;">
String hql = &quot;from User as u where u.group is ?&quot;;
return getHibernateTemplate().find(hql, null);
</pre>
<p>哈哈！好了！结果……(Debug查看返回的List的size为0)~ 8是吧……是不是要用其他的匹配词啊？于是我再次操刀写了：</p>
<pre class="brush: java;">
String hql = &quot;from User as u where u.group like ?&quot;;
return getHibernateTemplate().find(hql, null);
</pre>
<p>我都开始怀疑我是程序员了……竟然会用 like 匹配……我笑笑地试了一下。废话，当然还是失败了(Debug查看返回的List的size为0)。啊啊啊啊啊啊啊啊！shit！我打电话给了朋友，问他到底怎么办(他们公司推行Hibernate的开发)。结果他说啥：“一般不会查空的值吧……我不知道……你再试试看，好了告诉我怎么弄……”我差点没昏过去……</p>
<p>突然间，我灵光乍现“我他妈的就把HQL写死了，难道他还不出来？”</p>
<pre class="brush: java;">
String hql = &quot;from User as u where u.group is null&quot;;
return getHibernateTemplate().find(hql);
</pre>
<p>他妈的成功了……不过确实差异。时候我上网有心地留意了这方面的东西，发现有一个人他是使用Hibernate原生的Session进行查询也是在设置传入参数中输入了null，结果也是没有得到正确的结果，比较诧异啊！</p>
<p>总之，不管如何，功能是实现了~值得“庆幸”</p>
]]></content:encoded>
			<wfw:commentRss>http://www.agatezone.cn/code/archives/50/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>续：Struts2的OGNL的中文识别</title>
		<link>http://www.agatezone.cn/code/archives/48</link>
		<comments>http://www.agatezone.cn/code/archives/48#comments</comments>
		<pubDate>Thu, 03 Apr 2008 03:01:03 +0000</pubDate>
		<dc:creator>agate</dc:creator>
				<category><![CDATA[程序编码]]></category>
		<category><![CDATA[encoding]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[OGNL]]></category>
		<category><![CDATA[struts2]]></category>
		<category><![CDATA[webwork]]></category>

		<guid isPermaLink="false">http://www.agatezone.cn/code/?p=48</guid>
		<description><![CDATA[原来还是自己的问题……首先自我检讨一下，常常总是自以为是用自己的思维方式想问题。呵呵，这个真的是打开眼界啊！原来 OGNL 这个玩意有如此大的魔力，难怪 Struts2 使用他哈！厉害……
说道上回写的那个中文问题，本来是以为是转换成什么 Unicode 编码方式了，其实不然，只不过 Struts2 的 OGNL 有点低智商，只认 '' 符号里的西欧字符为字符串，其他的字符出现就会抛个 FormatException 异常……比较罕见，但是这个也使我研究了一小下 OGNL 的“真才实学”。
发现 Struts2 中
&#60;s:if test="#user.sex == 'male' "&#62; ... &#60;/s:if&#62;
是可以的
&#60;s:if test="#user.sex == '男' "&#62; ... &#60;/s:if&#62;
是不行的，必须改成
&#60;s:if test="#user.sex == '男'.toString() "&#62; ... &#60;/s:if&#62;
发现牛逼在何处了吧…… OGNL 竟然除了属性的调用，还可以调用方法。像上面这样使用的话，中文的 OGNL 比较就基本没有问题了。
]]></description>
			<content:encoded><![CDATA[<p>原来还是自己的问题……首先自我检讨一下，常常总是自以为是用自己的思维方式想问题。呵呵，这个真的是打开眼界啊！原来 OGNL 这个玩意有如此大的魔力，难怪 Struts2 使用他哈！厉害……</p>
<p>说道上回写的那个中文问题，本来是以为是转换成什么 Unicode 编码方式了，其实不然，只不过 Struts2 的 OGNL 有点低智商，只认 <span style="color: #ff0000;">''</span> 符号里的西欧字符为字符串，其他的字符出现就会抛个 FormatException 异常……比较罕见，但是这个也使我研究了一小下 OGNL 的“真才实学”。</p>
<p>发现 Struts2 中<br />
<code>&lt;s:if test="#user.sex == 'male' "&gt; ... &lt;/s:if&gt;<br />
是可以的</code><br />
<code>&lt;s:if test="#user.sex == '男' "&gt; ... &lt;/s:if&gt;<br />
是不行的，必须改成<br />
&lt;s:if test="#user.sex == '男'.toString() "&gt; ... &lt;/s:if&gt;</code></p>
<p>发现牛逼在何处了吧…… OGNL 竟然除了属性的调用，还可以调用方法。像上面这样使用的话，中文的 OGNL 比较就基本没有问题了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.agatezone.cn/code/archives/48/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>在GlassFish的WebService中需要注意的HashMap</title>
		<link>http://www.agatezone.cn/code/archives/45</link>
		<comments>http://www.agatezone.cn/code/archives/45#comments</comments>
		<pubDate>Wed, 02 Apr 2008 09:45:54 +0000</pubDate>
		<dc:creator>agate</dc:creator>
				<category><![CDATA[程序编码]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[glassfish]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[jaxws-ri]]></category>
		<category><![CDATA[opensource]]></category>

		<guid isPermaLink="false">http://www.agatezone.cn/code/?p=45</guid>
		<description><![CDATA[虽然如今的ws标准都已经很智能了，大多的数据类型都可以识别。但是在GlassFish中，发布的ws方法中参数和返回值不可以为hashmap的，但是如果非要要使用键值对该如何使用呢？
最简单的方法就是再次包装：

public class MapBean {
	private HashMap&#60;String,String&#62; hm;
	public HashMap&#60;String, String&#62; getHm() {
		return hm;
	}
	public void setHm(HashMap&#60;String, String&#62; hm) {
		this.hm = hm;
	}
}


@WebService()
public class HelloWorld {
	public HelloWorld() {
	}
	@WebMethod
	public MapBean getMapBean(HashMap&#60;String,String&#62; hm) {
		MapBean mb = new MapBean();
		hm.put(&#34;server&#34;, &#34;serverHashMap&#34;);
		mb.setHm(hm);
		System.out.println(&#34;Hello HashMap...&#34;);
		return mb;
	}
}

这样，加一层包装之后，就可以间接地使用Map了。
]]></description>
			<content:encoded><![CDATA[<p>虽然如今的ws标准都已经很智能了，大多的数据类型都可以识别。但是在GlassFish中，发布的ws方法中参数和返回值不可以为hashmap的，但是如果非要要使用键值对该如何使用呢？<br />
最简单的方法就是再次包装：</p>
<pre class="brush: java;">
public class MapBean {
	private HashMap&lt;String,String&gt; hm;
	public HashMap&lt;String, String&gt; getHm() {
		return hm;
	}
	public void setHm(HashMap&lt;String, String&gt; hm) {
		this.hm = hm;
	}
}
</pre>
<pre class="brush: java;">
@WebService()
public class HelloWorld {
	public HelloWorld() {
	}
	@WebMethod
	public MapBean getMapBean(HashMap&lt;String,String&gt; hm) {
		MapBean mb = new MapBean();
		hm.put(&quot;server&quot;, &quot;serverHashMap&quot;);
		mb.setHm(hm);
		System.out.println(&quot;Hello HashMap...&quot;);
		return mb;
	}
}
</pre>
<p>这样，加一层包装之后，就可以间接地使用Map了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.agatezone.cn/code/archives/45/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>p6spy和sqlProfiler的配合使用让你的hibernate的show_sql更好用</title>
		<link>http://www.agatezone.cn/code/archives/42</link>
		<comments>http://www.agatezone.cn/code/archives/42#comments</comments>
		<pubDate>Thu, 27 Mar 2008 11:20:16 +0000</pubDate>
		<dc:creator>agate</dc:creator>
				<category><![CDATA[未分类]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[util]]></category>

		<guid isPermaLink="false">http://www.agatezone.cn/code/?p=42</guid>
		<description><![CDATA[使用hibernate开发的朋友都知道，想在使用hibernate进行持久层操作的时候显示对应的sql语句，可以设置hibernate配置文件中的show_sql属性为true来实现这个需求。可是这个功能比较让人失望……他的语句是没错，但是参数值全是?这个带传入的参数符号，每个调试带来什么方便。
在这里，我介绍两个工具包来解决这个问题：[p6spy]和[sql_profiler]，具体主页地址在下列给出
p6spy: http://www.p6spy.com
SQL Profile: http://www.jahia.net/jahia/page597.html
我们先来说说p6spy这个工具。在我理解上，他其实就是一个中间驱动，在数据库调用端和实际数据库驱动间做一个代理人的角色，进而加入了一些特有的辅助功能。在这里我们使用的调用端就是hibernate这个数据持久层框架，而数据库驱动我们用的是mysql的默认驱动(一般就是com.mysql.jdbc.Driver)。好，解释完理论开始实际试验：
* 将p6syp.zip(可能是tar文件包)下载好
* 将包中的p6syp.jar包放入你工程的classpath下(web项目就丢到WEB-INF/lib中)
* 将包中的spy.properties放入src目录中
* 修改hibernate配置文件中的数据库驱动为com.p6spy.engine.spy.P6SpyDriver这个中间驱动
* 修改刚才拷贝进src中的spy.properties文件，将realdriver的值设置成原来hibernate中的真正驱动(这里我是com.mysql.jdbc.Driver)

OK搞定！重新编译项目，以保证p6syp.jar和spy.properties编译进入目标地址。
接着就运行你的程序吧，看看控制台……(不要打我啊，我又没说控制台会有变化=.=)。但是看看你的工程根目录下是不是出现了spy.log，这里面就是你要的数据库操作历史，包括了真正传入的参数的具体值。
如果需要改变spy.log日志的生成地址，可以对应设置spy.properties文件的logfile属性给出绝对地址。(logfile默认是spy.log可以加上路径比如logfile = c:\xxx\xxx.log)
好了，似乎hibernate的?参数问题解决了，但是我的好多朋友都抱怨：“怎么这个log格式这么难懂啊！看着好不爽啊！”的确！p6syp的日志格式让人确实分外头大，于是乎介绍个SQL Profile来帮帮痛苦的大众。
照惯例，介绍介绍理论知识。SQL Profiler是一个基于p6syp的一个辅助包，可以实现很多功能，比如根据你的query来帮你生成合适的索引功能。在这里我们使用它的GUI控制介面，说白了就是一个监听器，在你通过p6spy进行数据库操作时，他就会很清晰地跟踪并列出你的操作，比单单查看那个恶心的spy.log来得舒服！既然基于p6syp当然也要用到p6syp.jar这个包咯，只是必须使用我们下载到的sqlprofiler.zip中的spy.properties来替换原来的项目中的那个文件，因为这个文件是定制过的，所谓的监听器也是靠这个文件才起作用的。好，废话说多了毕竟会烦，来说说具体步骤：
* 将下载好的sqlprofiler.zip包中的 sqlprofiler.jar 和spy.properties两个文件解压出来
* 使用新的spy.properties文件替换工程中原来的那个文件
* 根据刚才添加p6syp的过程，修改 spy.properties 文件的参数
* 使用 java -jar sqlprofiler.jar 命令启动sqlprofiler的GUI介面
* 再次启动你的应用吧，看看是不是在进行数据持久层操作的时候sqlprofiler的GUI介面中便出现了对应的操作记录，很清晰的列了出来：

]]></description>
			<content:encoded><![CDATA[<p>使用hibernate开发的朋友都知道，想在使用hibernate进行持久层操作的时候显示对应的sql语句，可以设置hibernate配置文件中的show_sql属性为true来实现这个需求。可是这个功能比较让人失望……他的语句是没错，但是参数值全是?这个带传入的参数符号，每个调试带来什么方便。</p>
<p>在这里，我介绍两个工具包来解决这个问题：[p6spy]和[sql_profiler]，具体主页地址在下列给出<br />
p6spy: http://www.p6spy.com<br />
SQL Profile: http://www.jahia.net/jahia/page597.html</p>
<p>我们先来说说p6spy这个工具。在我理解上，他其实就是一个中间驱动，在数据库调用端和实际数据库驱动间做一个代理人的角色，进而加入了一些特有的辅助功能。在这里我们使用的调用端就是hibernate这个数据持久层框架，而数据库驱动我们用的是mysql的默认驱动(一般就是com.mysql.jdbc.Driver)。好，解释完理论开始实际试验：<br />
* 将p6syp.zip(可能是tar文件包)下载好<br />
* 将包中的p6syp.jar包放入你工程的classpath下(web项目就丢到WEB-INF/lib中)<br />
* 将包中的spy.properties放入src目录中<br />
* 修改hibernate配置文件中的数据库驱动为com.p6spy.engine.spy.P6SpyDriver这个中间驱动<br />
* 修改刚才拷贝进src中的spy.properties文件，将realdriver的值设置成原来hibernate中的真正驱动(这里我是com.mysql.jdbc.Driver)</p>
<p><img src="http://pic.yupoo.com/skyforce/6045754ef71b/1dwgk2wv/1dwgk2wv.jpg" /></p>
<p>OK搞定！重新编译项目，以保证p6syp.jar和spy.properties编译进入目标地址。</p>
<p>接着就运行你的程序吧，看看控制台……(不要打我啊，我又没说控制台会有变化=.=)。但是看看你的工程根目录下是不是出现了spy.log，这里面就是你要的数据库操作历史，包括了真正传入的参数的具体值。</p>
<p>如果需要改变spy.log日志的生成地址，可以对应设置spy.properties文件的logfile属性给出绝对地址。(logfile默认是spy.log可以加上路径比如logfile = c:\xxx\xxx.log)</p>
<p>好了，似乎hibernate的?参数问题解决了，但是我的好多朋友都抱怨：“怎么这个log格式这么难懂啊！看着好不爽啊！”的确！p6syp的日志格式让人确实分外头大，于是乎介绍个SQL Profile来帮帮痛苦的大众。</p>
<p>照惯例，介绍介绍理论知识。SQL Profiler是一个基于p6syp的一个辅助包，可以实现很多功能，比如根据你的query来帮你生成合适的索引功能。在这里我们使用它的GUI控制介面，说白了就是一个监听器，在你通过p6spy进行数据库操作时，他就会很清晰地跟踪并列出你的操作，比单单查看那个恶心的spy.log来得舒服！既然基于p6syp当然也要用到p6syp.jar这个包咯，只是必须使用我们下载到的sqlprofiler.zip中的spy.properties来替换原来的项目中的那个文件，因为这个文件是定制过的，所谓的监听器也是靠这个文件才起作用的。好，废话说多了毕竟会烦，来说说具体步骤：<br />
* 将下载好的sqlprofiler.zip包中的 sqlprofiler.jar 和spy.properties两个文件解压出来<br />
* 使用新的spy.properties文件替换工程中原来的那个文件<br />
* 根据刚才添加p6syp的过程，修改 spy.properties 文件的参数<br />
* 使用 java -jar sqlprofiler.jar 命令启动sqlprofiler的GUI介面<br />
* 再次启动你的应用吧，看看是不是在进行数据持久层操作的时候sqlprofiler的GUI介面中便出现了对应的操作记录，很清晰的列了出来：</p>
<p><img src="http://pic.yupoo.com/skyforce/4306555a5aa3/ng2xhhvh.jpg" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.agatezone.cn/code/archives/42/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>再谈对象匹配之HashCode&amp;Equals</title>
		<link>http://www.agatezone.cn/code/archives/40</link>
		<comments>http://www.agatezone.cn/code/archives/40#comments</comments>
		<pubDate>Sat, 15 Mar 2008 01:09:47 +0000</pubDate>
		<dc:creator>agate</dc:creator>
				<category><![CDATA[程序编码]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.agatezone.cn/code/?p=40</guid>
		<description><![CDATA[相信每位初学OOP的同学都知道在这面向对象的世界里比较两个对象的方法是使用Equals来实现，可是如何写一个比较完美的又代码量小的Equals函数呢？
还有就是在散列表的数据结构中，散列表自身的数据结构算法需要用到对象比较的方法HashCode，所以常常我们会听到“老者”对我们谆谆而训曰：重写Equals方法是必须的，可是别忘了重写HashCode哦！
HashCode和Equals这两个方法的渊源可谓不浅，在这里我通过简单的代码片段，展示一个目前常用的比较完美且代码量小的方法重写方式：

	/**
	 * 这里我们假定改类的名字为Example
	 */

	@Override
	public int hashCode() {
		int result = 关键属性.hashCode();
		//这里31其实可以由任何一个质素代替，用来保证hashcode的不重复
		result = 31 * result;
		//关键属性不止一个的话可以加上
		//result = result + 关键属性2.hashCode() + ……;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}

		if (obj == null) {
			return false;
		}

		if (getClass() != obj.getClass()) {
			return false;
		}

		Example other = (Example) obj;

		//如果关键属性不止一个的话就多写几个判断
		if (!关键属性.equals(other.关键属性)) {
			return false;
		}

		return true;
	}

]]></description>
			<content:encoded><![CDATA[<p>相信每位初学OOP的同学都知道在这面向对象的世界里比较两个对象的方法是使用Equals来实现，可是如何写一个比较完美的又代码量小的Equals函数呢？</p>
<p>还有就是在散列表的数据结构中，散列表自身的数据结构算法需要用到对象比较的方法HashCode，所以常常我们会听到“老者”对我们谆谆而训曰：重写Equals方法是必须的，可是别忘了重写HashCode哦！</p>
<p>HashCode和Equals这两个方法的渊源可谓不浅，在这里我通过简单的代码片段，展示一个目前常用的比较完美且代码量小的方法重写方式：</p>
<pre class="brush: java;">
	/**
	 * 这里我们假定改类的名字为Example
	 */

	@Override
	public int hashCode() {
		int result = 关键属性.hashCode();
		//这里31其实可以由任何一个质素代替，用来保证hashcode的不重复
		result = 31 * result;
		//关键属性不止一个的话可以加上
		//result = result + 关键属性2.hashCode() + ……;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}

		if (obj == null) {
			return false;
		}

		if (getClass() != obj.getClass()) {
			return false;
		}

		Example other = (Example) obj;

		//如果关键属性不止一个的话就多写几个判断
		if (!关键属性.equals(other.关键属性)) {
			return false;
		}

		return true;
	}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.agatezone.cn/code/archives/40/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spring的OpenSessionInView</title>
		<link>http://www.agatezone.cn/code/archives/36</link>
		<comments>http://www.agatezone.cn/code/archives/36#comments</comments>
		<pubDate>Thu, 31 Jan 2008 08:44:17 +0000</pubDate>
		<dc:creator>agate</dc:creator>
				<category><![CDATA[程序编码]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[OpenSessionInView]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://www.agatezone.cn/code/?p=36</guid>
		<description><![CDATA[所谓 OpenSessionInView 就是真对 Hibernate 这个数据持久层框架的一个Web下的使用技巧。我们在日常 MVC 程序开发的过程中，如果使用的是 Hibernate 的数据持久层框架，一定常常在业务逻辑层中出现 Session is closed 的 laze 异常，这是由于 Hibernate 的Session 在上一个操作中我们为了保证 Session  已经及时的回收时被我们关掉了。
我们常常被放在一个很尴尬的地带：我们的 DAO 成负责 CRUD  在执行完成后根据我上面说的那个“好习惯”，肯定要把本次操作的Session关掉，或者说在一个点统一被关掉。那么导致的结果是，当我拿到我们需要的对象时，该对象虽然说是数据完整的，但是他可能有一个 Link 对象，这个对象可是不完整的！顶多是一个包含 ID 的空壳。那很自然的，当我们要访问这个对象中的 Link 对象的某个非ID值的时候，必然抛出“Laze”异常。如果我们之前不关闭那个 Session 似乎一般的解决方案没法告诉在下一个使用层的代码何时关闭，虽然可以成功访问 Link 对象，但是长此以往 Session 就大大占用内存了。
如何设计才好呢？在很多 Hibernate 的使用者中就有人很早地提出了 Open Session In View 这个Web开发的重要理念，即让 Hibernate 的 Session 在整个请求周期中生存（包括建立和消亡）。当然这个是理念，实现手段有很多种了，包括什么参数传递、建立辅助包等等等等。这里我们专门提及 Spring 这个万能的整合型框架是如何处理的。
Spring 为我们提供了一个叫做 OpenSessionInViewFilter 的过滤器，他是标准的 Servlet [...]]]></description>
			<content:encoded><![CDATA[<p>所谓 OpenSessionInView 就是真对 Hibernate 这个数据持久层框架的一个Web下的使用技巧。我们在日常 MVC 程序开发的过程中，如果使用的是 Hibernate 的数据持久层框架，一定常常在业务逻辑层中出现 Session is closed 的 laze 异常，这是由于 Hibernate 的Session 在上一个操作中我们为了保证 Session  已经及时的回收时被我们关掉了。</p>
<p>我们常常被放在一个很尴尬的地带：我们的 DAO 成负责 CRUD  在执行完成后根据我上面说的那个“好习惯”，肯定要把本次操作的Session关掉，或者说在一个点统一被关掉。那么导致的结果是，当我拿到我们需要的对象时，该对象虽然说是数据完整的，但是他可能有一个 Link 对象，这个对象可是不完整的！顶多是一个包含 ID 的空壳。那很自然的，当我们要访问这个对象中的 Link 对象的某个非ID值的时候，必然抛出“Laze”异常。如果我们之前不关闭那个 Session 似乎一般的解决方案没法告诉在下一个使用层的代码何时关闭，虽然可以成功访问 Link 对象，但是长此以往 Session 就大大占用内存了。</p>
<p>如何设计才好呢？在很多 Hibernate 的使用者中就有人很早地提出了 Open Session In View 这个Web开发的重要理念，即让 Hibernate 的 Session 在整个请求周期中生存（包括建立和消亡）。当然这个是理念，实现手段有很多种了，包括什么参数传递、建立辅助包等等等等。这里我们专门提及 Spring 这个万能的整合型框架是如何处理的。</p>
<p>Spring 为我们提供了一个叫做 OpenSessionInViewFilter 的过滤器，他是标准的 Servlet Filter 所以我们把它按照规范配置到 web.xml 中方可使用。使用中我们必须配合使用 Spring 的 HibernateDaoSupport 来进行开发，也就是说，我们的dao层的类都要继承于 HibernateDaoSupport，从中由 Spring 来控制 Hibernate 的 Session 在请求来的时候开启，走的时候关闭，保证了我们访问数据对象时的稳定性。</p>
<p>下面我大概描述一下使用的方法：</p>
<p>1. 在 web.xml 中加入对应过滤器配置文件</p>
<pre class="brush: xml;">
&lt;!-- Spring的OpenSessionInView实现 --&gt;
&lt;filter&gt;
	&lt;filter-name&gt;openSessionInViewFilter&lt;/filter-name&gt;
	&lt;filter-class&gt;
		org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
	&lt;/filter-class&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
	&lt;filter-name&gt;openSessionInViewFilter&lt;/filter-name&gt;
	&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;
</pre>
<p>2. 在我们访问持久层数据是使用 Spring 为我们的 HibernateDaoSupport 的支持，并使用其中的对应方法操作我们的持久层数据</p>
<pre class="brush: java;">
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public class XxxDAO extends HibernateDaoSupport {

	public void save(Xxx transientInstance) {
		try {
			getHibernateTemplate().save(transientInstance);
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public void delete(Xxx persistentInstance) {
		try {
			getHibernateTemplate().delete(persistentInstance);
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public Xxx findById(Integer id) {
		try {
			Role instance = (Xxx) getHibernateTemplate().get(&quot;Xxx&quot;, id);
			return instance;
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public List findByProperty(String propertyName, Object value) {
		try {
			String queryString = &quot;from Xxx as model where model.&quot;
					+ propertyName + &quot;= ?&quot;;
			return getHibernateTemplate().find(queryString, value);
		} catch (RuntimeException re) {
			throw re;
		}
	}
}
</pre>
<p>其实啊，就是调用 HibernateDaoSupport 中的 getHibernateTemplate() 这个模板方法，再使用里头的对应对持久层操作的方法。</p>
<p>这样，Spring 这个优秀的整合型框架就是轻松地帮我们把烦恼已久的问题解决了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.agatezone.cn/code/archives/36/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
