2007-07-25

因无索引导致的性能问题

测试那边说, 页面打开很慢, 自己跑去试了下, 果然, 一个搜索结果页面, 大概要30s~60s, 查看了下代码, 发现是段hql执行问题, 就抽取出来单独测试, 这个查询类似这样的结构:
select count(*) from a, b where a.bid = b.bid;

其中a表中的bid是b表的id外键. 每个表大概有7k条记录.这个查询每次都耗时30s, 后来把a表中的bid字段建立个属性, 速度就快多了, 大概是300ms~1s.

以前一直没觉得索引有这么神奇的效果.....

--
It's Hard to Define, But I Know it When I See it…

2007-07-24

接口参数类型

之前写过一个接口, 目的是更新FriendLink对象到数据库.形式如下:

update(FriendLink link);

接口的实现是这么写的:
update(FriendLink link){
    dao.update(link);
}

后来, 发现有弊病在: 这个接口依赖这样的事实: link已经存在于数据库中 .这样很容易产生潜在的不安全性, 外部的任何程序都可以随意构造一个FriendLink实例(而不是从数据库中取然后稍加修改而成的), 然后传入到这个接口, 然后产生异常. 还有个问题就是, 它限制了访问媒介为java对象(须先构造出FriendLink对象来, 才能访问到这个接口), 不利于其它形式的访问(如webServices, REST等---虽然可以, 但是须对FriendLink中accessor信息了然于胸). 所以应修改如下:

update(long friendLinkId);

传入基本类型(long), 声明说会对这个(id为friendLinkId的FriendLInk)作更新, 这样, link已经存在于数据库中  这样的谓词是由接口内部来判断处理的. 对于其它形式的访问, 基本类型都是被支持的. 至于update的信息, 可以以参数形式, 或函数名形式展现, 如下:
update(long frindLinkId, Date accessDate); ①

updateAccessDate(long friendLinkId);②

象②这样的只传入id的接口, 依赖于"执行更新所需信息可以从接口上下文得到", 比如当前时间等.所以应用面比较狭窄, 不知道具体应该怎么处理(map参数?) :( (还是动态语言比较好, 象js的arguments参数很灵活)

--
It's Hard to Define, But I Know it When I See it…

date 与 timestamp 类型

用一句话说就是:
timestamp比date精确.
用date只能搞到日期, 时间得不到, 所以在sql里面进行alter时, 只有timestamp=>date的转换, 如果想执行相反的转换会报异常.

如果用hibernate进行映射, 一般来说是 java.util.Date=>timestamp.否则, 标志性的异常信息是batch update exception (不过有个有趣的现象是, 如果你设置hibernate.jdbc.batch_size 为0的话, 就能顺利执行, 应该是hibernate的bug)
P.S. 如果是用xdoclet映射字段, 不要这么写:
@hibernate.property column="createDate" type="date" 
把type写全:java.util.Date. 否则会引来不必要的麻烦: hibernate会把它错当成java.sql.Date :(

--
It's Hard to Define, But I Know it When I See it…

2007-06-28

将unicode转成中文及其它

找不到源文件了, 只好把.properties反转换成中文了
原理就是把.properties中的所有"\uxxxx"形式的转成对应的中文.

String r = FileUtils.readFileToString(new File("d:/aa.TXT"), "utf-8");
Pattern p = Pattern.compile("\\\\u([a-zA-Z0-9]{4})");
String t = "";
Matcher m = p.matcher(r);
while(m.find())
{
    t = m.group(1);
    r = r.replaceFirst("\\\\u([a-zA-Z0-9]{4})", String.valueOf(Character.toChars(Integer.parseInt(t, 16))));
}
System.out.println(r);

那个parseInt中的参数16表示t是16进制的字符串.
感觉还比较简洁的说~~~

P.S. FileUtils是jakarta commons.io里的

--
It's Hard to Define, But I Know it When I See it…

2007-06-14

httpclient提交中文的问题.

提交的时候老出错, 把我的中文全给搞成问号, 后来看服务器上有个encodingfilter, 貌似只接收utf-8的.

本来想的是看看httpclient里面哪里编码不对了, 改成utf-8,如此的思路.

后来, 发现给http head加个meta就成了:
post.addRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");

真的是不能想太复杂鸟...

--
It's Hard to Define, But I Know it When I See it…

2007-06-07

其实, 除了actionForm还有更简便的方式的~

Spring的这个databinder真是好用:

FriendLink bean = new FriendLink();
ServletRequestDataBinder binder = new ServletRequestDataBinder(bean, "link");
CustomDateEditor editor = new CustomDateEditor(new SimpleDateFormat("yyyy-M-d"), true);
binder.registerCustomEditor(Date.class, editor);
binder.bind(request);

这样就自动给bean注入值了, 而且它已经自动拥有了处理multipart的能力, 真是不错. 只是没有处理日期格式的能力, 但是象上面的代码就可以了.

顺便贴几个链接:
link 用spring做项目时的一些设计上的技巧.
link ServletRequestDataBinder的官方文档.
link 处理日期格式的方法就是从他这抄袭来的, 呵呵.

--
It's Hard to Define, But I Know it When I See it…

2007-05-13

补: autoboxing

网上搜NPE,发现了别人碰到同样的问题.这些人还建议不要用autoboxing. 有句倒说的很到位:The root cause of the NPE-related weirdness is that Java doesn't distinguish between pointers and "pointers that can be null". 这也应该是autoboxing问题的根源。

P.S. NPE=NullPointerException(看来这个异常很常见呢)