前一阵在研究o/r mapping,觉得hibernate和ibatis都是好东西,但ibatis更容易上手,而且跟数据库打交道的时候只需把sql 语句配置在xml里即可,不象hibernamte要写复合其规范的hql。当然现在hibernate大行其道肯定是有道理的,我过一阵子也打算好好学习一下。
技术发展的太快,学习方法是很重要的。(看来开源确实促进了生产力的发展啊,由此推断,共产主义社会肯定会实现的啦。)我认为必须摒弃抱本书按部就班的学习方法,而应该是study in action,在实践中学习,缺啥补啥,大不了不断重构好了。当然前提是有一定的技术积累了。 为了学习ibatis,除了大致看了一下ibatis的官方文档,我把主要精力放在研究作者的范例jpetstore上了,大家可以道www.ibatis.com去下载4.0版本的例子,3.x的不要下了,代码写的没有4.0的优美。 然后再去下载mysql,tomcat,安装调试让jetstore跑起来。这个过程我就不讲了,大家动动脑筋找点成就感吧。工欲善其事,必先利其器。我用的是jbuilder9,因为我以前用delphi的对borland的产品有感情啊(当然borland不会对我有感情,因为。。。。。。^_^,中国特色)。建一个新项目,保存后关掉project,然后把jpetstore的代码包拷贝到:project rc\下,再打开刚才的项目,顺利的话你就能看到项目下的一堆包啦。现在编译肯定是有问题的,别急别急,在项目里加载上jpetstore源码lib目录下的所有.jar和servlet.jar,为了连mysql,你还得加载mysql的jdbc驱动。具体做法,你可以在jbuilder9 tools\config libraries 新建三个lib,比如ibatislib里放上jpetstore源码lib目录下的所有.jar,servlet就不要建了,jb9里带了,再建一个mysqllib放上mysql的jdbc驱动的.jar,然后修改jpetstore源码src\properties\database.properties的内容,例如,我的是driver=org.gjt.mm.mysql.driverurl=jdbc:mysql://localhost/jpetstoreusername=jpetstorepassword=ibatis9977现在make project应该可以通过了。好啦,打开com.ibatis.jpetstore底下的所有.java文件吧。domain目录下放的是javabean,一般是跟表相对应的。persistence目录下放的是dao接口和具体实现类,dao即数据访问对象(data access object),是用来跟数据库打交道的。ibatis的o/r mapping的使用方法也就在这个目录里面。presentation目录下放的是formbean,后面还要说到jpetstore范例对struts的创造性使用。service目录下放的是service类,通过service对象调用dao对象的方法来访问数据库的,这是一种常用的设计模式。 常见的struts编程应该是一个动作对应一个action,例如写一个交友网站,用户登录和用户查询就得写分别写两个action来处理。而jpetstore的作者克林顿(clinton begin,名字够响亮的)写了一个action动态的调用formbean的不同方法来处理不同的动作。代码如下,注意execute()的写法!
public class beanaction extends action {
public actionforward execute(actionmapping mapping,
actionform form, httpservletrequest request,
httpservletresponse response)
throws exception {
string forward = “success”;
try {
actioncontext.initialize(request, response);
if (form != null) {
// explicit method mapping
method method = null;
string methodname = mapping.getparameter();
if (methodname != null && !”*”.equals(methodname)) {
try {
method = form.getclass().getmethod(methodname,
null); forward = (string) method.invoke(form, null);
} catch (exception e) {
throw new beanactionexception(“error dispatching
bean action via method parameter (” + methodname + “).
cause: ” + e, e);
}
}
// path based method mapping
if (method == null && !”*”.equals(methodname)) {
methodname = mapping.getpath();
if (methodname.length() > 1) {
int slash = methodname.lastindexof(“/”) + 1;
methodname = methodname.substring(slash);
if (methodname.length() > 0) {
try {
method = form.getclass().getmethod
(methodname, null);
forward = (string) method.invoke(form, null);
} catch (exception e) {
throw new beanactionexception(“error dispatching
bean action via url pattern (” + methodname + “).
cause: ” + e, e);
}
}
}
}
}
} catch (exception e) {
request.setattribute(“beanactionexception”, e);
throw e;
}
return mapping.findforward(forward);
}
}
也就是通过对struts-config.xml的配置信息的读取来决定调用的方法,或者是不调用任何方法。例如: 当actionservlet收到请求/shop/viewcategory.shtml,(jpetstore里后缀定义的是“.shtml”)调用catalogbean的viewcategory方法。怎么样,有创意吧,如果你愿意,就再也不用写那么多的action了。下面谈一谈ibatis的o/r mapping吧。请大家打开目录your project\com\ibatis\jpetstore\persistence qlmapdao ql,看到了什么?除了配置文件sql-map-config.xml以外,是一些和javabean相对应的xml,打开sql-map-config.xml和acount.xml看看吧,再返到your project\com\ibatis\jpetstore\persistence目录,打开dao.xml发现他们的关系了吧。可能这时你搞不清这些xml有什么用处,别急,ibatis官方文档里说的很清楚(有中文版的哦)。我大致说一下跟javabean对应的那些xml文件的作用吧,比如acount.xml,是映射javabean和数据库的表的文件。你可以按照ibatis的规范在里面写任意的sql语句,参数和返回值可以是基本类型及其包装类,map,自定义的类。最常用的当然是返回自定义类实例了。不过如果返回值是自定义的类实例的话,你就需要先定义resultmap,比如:<resultmap id=”accountresult” class=”account”> <result property=”username” column=”userid”/> <result property=”email” column=”email”/> <result property=”firstname” column=”firstname”/> <result property=”lastname” column=”lastname”/> <result property=”status” column=”status”/> <result property=”address1″ column=”addr1″/> <result property=”address2″ column=”addr2″/> <result property=”city” column=”city”/> <result property=”state” column=”state”/> <result property=”zip” column=”zip”/> <result property=”country” column=”country”/> <result property=”phone” column=”phone”/> <result property=”languagepreference” column=”langpref”/> <result property=”favouritecategoryid” column=”favcategory” /> <result property=”listoption” column=”mylistopt” /> <result property=”banneroption” column=”banneropt” /> <result property=”bannername” column=”bannername” /> <resultmap>然后再引用:<select id=”getaccountbyusername” resultmap=”accountresult” parameterclass=”string”> select signon.username as userid, account.email, account.firstname, account.lastname, account.status, account.addr1, account.addr2, account.city, account.state, account.zip, account.country, account.phone, profile.langpref, profile.favcategory, profile.mylistopt, profile.banneropt, bannerdata.bannername from account, profile, signon, bannerdata where account.userid = #value# and signon.username = account.userid and profile.userid = account.userid and profile.favcategory = bannerdata.favcategory <select>再打开accountsqlmapdao.java看看:
public account getaccount(string username) { return (account) queryforobject(“getaccountbyusername”, username); }
思考一下,看明白其中的关联了吧。打开accountservice.java:
public account getaccount(string username) {
return accountdao.getaccount(username);
}
打开accountbean.java:
public string newaccount() {
try {
accountservice.insertaccount(account);
account = accountservice.getaccount
(account.getusername());//在这调用的
mylist = catalogservice.getproductlistbycategory
(account.getfavouritecategoryid());
authenticated = true;
repeatedpassword = null;
return “success”;
} catch (exception e) {
throw new beanactionexception (“there was a problem
creating your account information. cause: ” + e, e); }
}
看了半天,写个例子试试吧
package com.ibatis.jpetstore.service;
import com.ibatis.dao.client.daomanager;
import com.ibatis.jpetstore.domain.*;
import com.ibatis.jpetstore.persistence.daoconfig;
import com.ibatis.common.util.paginatedlist;
import com.ibatis.jpetstore.persistence.iface.*;
import java.util.*;
public class ibatistest {
private daomanager daomanager =
daoconfig.getdaomanager();
private accountdao accountdao;
public ibatistest() {
accountdao = (accountdao) daomanager.getdao
(accountdao.class);
account account=accountdao.getaccount(“j2ee”, “j2ee”);
system.out.println(account.getfirstname());
}
public static void main(string[] args) {
ibatistest ibatistest=new ibatistest();
}
}
你还可以试试insert,update,delete。ibatis里可是支持分页的,用起来很爽的,大家有空还是花点功夫钻研一下吧。关于debug:我前两天照搬jpetstore的架构试着写了一个交友网站,基本上挺顺利,只是感觉debug比较麻烦,通常为了找一个错花上几个小时。jbuilder带的debug我没用过,但可是肯定肯定和delphi上的debug是有天壤之别的。而且junit我也是刚开始学,也没用上。这里,我把自己比较土的办法介绍一下:一, 当你写了新的o/r mapping的时候,可以先写个包含main方法的类测试一下,就向我上面的测试例子一样。二, 当你想跟踪变量值的时候,你可以利用ibatis带的工具类actioncontext把变量写到session里,比如你有你个formbean:userbean.java,其中有一个方法是处理用户登录的,你为了跟踪用户的用户名和密码,可以这样写:
public string logon() {
try {
user = userservice.getuser(user.getusername(),
user.getpassword());
if (user== null ) {
clear();
return “failure”;
} else {
user.setpassword(null);
authenticated = true;
user.setmessagecount
(messageservice.getmessagenewcount(user.getuserid()));
actioncontext.getactioncontext().setsimplemessage
(“newcount=”+newcount.tostring()+”
touserid=”+user.getuserid());//写入session
return ” failure “;}//导入到error.jsp
}catch (exception e){
throw new beanactionexception (“there was a problem
logoning your account information. cause: ” + e, e);
}
}
当然你需要包含下面的语句
import com.ibatis.struts.actioncontext;
error.jsp:
<%@ taglib uri=”struts-logic” prefix=”logic” %>
<%@ taglib uri=”struts-bean” prefix=”bean” %>
<%@ taglib uri=”struts-html” prefix=”html” %>
<%@ page import=”java.io.printwriter”%>
<logic:present name=”message”>
<bean:write
name=”message” />
</logic:present>
//输出你需要的信息
<logic:present name=”errors”>
<logic:iterate id=”error” name=”errors”>
<bean:write name=”error” />
</logic:iterate>
</logic:present>
<logic:notpresent name=”beanactionexception”>
<logic:notpresent name=”message”>
something happened…
but no further information was provided.
</logic:notpresent>
</logic:notpresent>
<logic:present name=”beanactionexception”>>
error!
property=”class.name”/>
<bean:write name=”beanactionexception”
property=”message”/>
</logic:present>
<logic:present name=”beanactionexception”>
stack
<%
exception e = (exception)request.getattribute
(“beanactionexception”);
e.printstacktrace(new printwriter(out));
%>
</logic:present>
三, 为跟踪变量,你还可以利用log4j把变量值写到log里去,这种方法很常见,不明白就去www.google.com查吧。四, 为避免写javabean出现大小写或其他的错误,强烈建议不要把bean当做普通class来写,要用ide 新建一个bean,这样ide会帮你找出很多错误。我就吃了不少苦头。入门了吗?有问题请留言。为了贴上xml费了老鼻子劲,不容易啊。我要开始研究spring和hibernate啦。
