by agate - Published: 2008-09-01 [11:09 下午] - Category: 程序编码
老是觉得 syntaxhighlighter-plus 默认的样式和现在的模板不是很搭配, 就是觉得宽度稍微窄了点~ 就操刀小改了一下这个插件的样式表. 改动如下:
.dp-highlighter {
/* 修改 */
width: 640px;
/* 添加 */
height: expression(this.scrollHeight > 320 ? "320px" : "auto");
max-height: 320px;
/* 注释 */
/* overflow: auto; */
}
这样便达到刚好的宽度, 合适的高度. 这里要提及一下从中学了一招~ 就是 IE 不支持 css 的 max-height 属性, 但是支持自家的 expression 表达式! 所以可以如上进行 hack 得到和标准同样的效果! 这个方法学习自 LINK
by agate - Published: 2008-04-06 [4:38 下午] - Category: 程序编码
今天郁闷了2个小时,不停地试验,就是没成功……(试验什么呢?)就是这个,用HQL来查出一个List,条件是某个字段为空。
两个领域类:
public class User {
private String username;
private Group group;
// ------------- setter
// ------------- getter
}
public class Group {
private String groupName;
private List<user> users;
// ------------- setter
// ------------- getter
}
让你查数据库中所有group为空的(即加入组的)所有用户。
Read more...
by agate - Published: 2008-04-03 [11:01 上午] - Category: 程序编码
原来还是自己的问题……首先自我检讨一下,常常总是自以为是用自己的思维方式想问题。呵呵,这个真的是打开眼界啊!原来 OGNL 这个玩意有如此大的魔力,难怪 Struts2 使用他哈!厉害……
说道上回写的那个中文问题,本来是以为是转换成什么 Unicode 编码方式了,其实不然,只不过 Struts2 的 OGNL 有点低智商,只认 '' 符号里的西欧字符为字符串,其他的字符出现就会抛个 FormatException 异常……比较罕见,但是这个也使我研究了一小下 OGNL 的“真才实学”。
发现 Struts2 中
<s:if test="#user.sex == 'male' "> ... </s:if>
是可以的
<s:if test="#user.sex == '男' "> ... </s:if>
是不行的,必须改成
<s:if test="#user.sex == '男'.toString() "> ... </s:if>
发现牛逼在何处了吧…… OGNL 竟然除了属性的调用,还可以调用方法。像上面这样使用的话,中文的 OGNL 比较就基本没有问题了。
by agate - Published: 2008-04-02 [5:45 下午] - Category: 程序编码
虽然如今的ws标准都已经很智能了,大多的数据类型都可以识别。但是在GlassFish中,发布的ws方法中参数和返回值不可以为hashmap的,但是如果非要要使用键值对该如何使用呢?
最简单的方法就是再次包装:
public class MapBean {
private HashMap<String,String> hm;
public HashMap<String, String> getHm() {
return hm;
}
public void setHm(HashMap<String, String> hm) {
this.hm = hm;
}
}
@WebService()
public class HelloWorld {
public HelloWorld() {
}
@WebMethod
public MapBean getMapBean(HashMap<String,String> hm) {
MapBean mb = new MapBean();
hm.put("server", "serverHashMap");
mb.setHm(hm);
System.out.println("Hello HashMap...");
return mb;
}
}
这样,加一层包装之后,就可以间接地使用Map了。
by agate - Published: 2008-03-27 [7:20 下午] - Category: 未分类
使用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介面中便出现了对应的操作记录,很清晰的列了出来:

by agate - Published: 2008-03-15 [9:09 上午] - Category: 程序编码
相信每位初学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;
}
by agate - Published: 2008-01-31 [4:44 下午] - Category: 程序编码
所谓 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 Filter 所以我们把它按照规范配置到 web.xml 中方可使用。使用中我们必须配合使用 Spring 的 HibernateDaoSupport 来进行开发,也就是说,我们的dao层的类都要继承于 HibernateDaoSupport,从中由 Spring 来控制 Hibernate 的 Session 在请求来的时候开启,走的时候关闭,保证了我们访问数据对象时的稳定性。
下面我大概描述一下使用的方法:
1. 在 web.xml 中加入对应过滤器配置文件
<!-- Spring的OpenSessionInView实现 -->
<filter>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>openSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2. 在我们访问持久层数据是使用 Spring 为我们的 HibernateDaoSupport 的支持,并使用其中的对应方法操作我们的持久层数据
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("Xxx", id);
return instance;
} catch (RuntimeException re) {
throw re;
}
}
public List findByProperty(String propertyName, Object value) {
try {
String queryString = "from Xxx as model where model."
+ propertyName + "= ?";
return getHibernateTemplate().find(queryString, value);
} catch (RuntimeException re) {
throw re;
}
}
}
其实啊,就是调用 HibernateDaoSupport 中的 getHibernateTemplate() 这个模板方法,再使用里头的对应对持久层操作的方法。
这样,Spring 这个优秀的整合型框架就是轻松地帮我们把烦恼已久的问题解决了。