分享
 
 
 

从Jpetstore 开始IBATIS之旅

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

前一阵在研究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\src\下,再打开刚才的项目,顺利的话你就能看到项目下的一堆包啦。现在编译肯定是有问题的,别急别急,在项目里加载上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.Driver

url=jdbc:mysql://localhost/jpetstore

username=jpetstore

password=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\sqlmapdao\sql,看到了什么?除了配置文件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!

name="BeanActionException"

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啦。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有