Archive for the ‘ iBatis ’ Category


iBatis学习记录(4)

今天主要的研究是关于ibatis的DAO。DAO全名是Data Access Object,有它的存在解决了数据库使用中的一个问题,就是如何面对不同的数据库资源进行相同的处理。在DAO下,规定了数据库操作的接口,于是面对不同的数据库资源,只需要分别实现相关接口就可以。提供接口API给用户能是用户更加方便的操作数据库,减少麻烦,避免一些可以避免的错误。

在使用之前,必须下载ibatis的dao包,因为在直接下载的ibatis包中是不含dao部分的。下载页面的右下角就有下载。

首先,来看一下ibatis的DAO结构,其核心就在一个dao.xml配置文件中。
<daoConfig>
<context id=”sqlmap”>
<transactionManager type=”SQLMAP”>
<property name=”SqlMapConfigResource” value=”com/featheast/daobasic/SqlMapConfig.xml”/>
</transactionManager>
<dao interface=”com.featheast.daobasic.UserDao”
implementation=”com.featheast.daobasic.UserDaoImpl”/>
</context>
</daoConfig>
在这个配置文件中,定义了当前的上下文环境,使用的TransactionManager,这个可以直接使用前面已经用过的manager,以及相对应的一组dao接口和实现类。很直观简洁。所有的DAO都是围绕着这个配置文件展开的。

接口定义了需要操作的方法,如下所示,基本包含了常见的CRUD方法:
public interface UserDao {
public void insert(UserBean user);
public void update(UserBean user);
public int delete(UserBean user);
public int delete(Integer id);
public List<UserBean> getUserList(UserBean user);
public List<Map<String, Object>> getMapList(UserBean user);
public UserBean getById(Integer id);
public UserBean getUser(UserBean user);
}

然后仍然是按照前面的定义SqlMapConfig.xml 和 SqlMap.xml,分别管理transactionManager和sql映射。

最后就是完成实现接口类:
public class UserDaoImpl extends SqlMapDaoTemplate implements UserDao {
public UserDaoImpl(DaoManager daoManager){
super(daoManager);
}
public int delete(UserBean user) {
// TODO Auto-generated method stub
return delete(user.getId());
}
public int delete(Integer id) {
// TODO Auto-generated method stub
return delete(”UserBean.delete”,id);
}
public UserBean getById(Integer id) {
// TODO Auto-generated method stub
return (UserBean)queryForObject(”UserBean.getById”,id);
}
public List<Map<String, Object>> getMapList(UserBean user) {
// TODO Auto-generated method stub
return queryForList(”UserBean.getMapList”,user);
}
public UserBean getUser(UserBean user) {
// TODO Auto-generated method stub
return null;
}
public List<UserBean> getUserList(UserBean user) {
// TODO Auto-generated method stub
return queryForList(”UserBean.getUserList”,user);
}
public void insert(UserBean user) {
// TODO Auto-generated method stub
insert(”UserBean.insert”,user);
}
public void update(UserBean user) {
// TODO Auto-generated method stub
update(”UserBean.update”,user);
}
}
首先要注意的是该类扩展了SqlMapDaoTemplate,这就可以直接在该类中调用常见的数据库操作方法而不需要生成一个SqlClient的实例。

最后是测试类:
public static void main(String[] args) {
// TODO Auto-generated method stub
DaoManager manager=GetDaoManager.getDaoManager();
//UserDaoImpl impl=new UserDaoImpl(manager);
UserDao impl=(UserDao)manager.getDao(UserDao.class);
System.out.println(impl.delete(108));
//System.out.println(impl.getById(108));
UserBean user=new UserBean();
user.setDay(”7″);
user.setEmail(”123@123.com“);
user.setMonth(”1″);
user.setName(”fea”);
user.setPwd(”123″);
user.setQq(”222″);
user.setUid(”fea”);
user.setYear(”1000″);
impl.insert(user);
}
其中有很重要的一点要注意的,就是在初始化impl的时候,不能直接使用构造函数,不然就会在后面出现NEP报错,地点应该是在getTransaction()方法中,第108行。这个问题花了我半个小时,最后才在Goolge上找到一个人出了同样的问题,用UserDao impl=(UserDao)manager.getDao(UserDao.class);这个方法解决的。

iBatis学习记录(3)

在ibatis中,会发现其输入参数只能有一个,于是当出现需要进行多个输入参数的时候,就要想点办法了,我看到的有以下两种比较好的方法能够解决这个问题
1) 用String代替
<select id=”checkLogin” parameterClass=”java.lang.String” resultClass=”java.lang.Integer”>
SELECT count(*) AS value FROM userinfo WHERE $sql$
</select>
比如如上的map statement代码中,将输入的参数设置为String类型,而在select语句中直接使用该String,于是用户可以在Java程序代码中手工植入需要匹配的参数。

String sql = “uid = ‘” + username + “‘ and pwd=’” + password + “‘”;
Integer r = (Integer) sqlMap.queryForObject(”checkLogin”, sql);

这个方法很简单,但是弊端也很多。首先得需要用户自己手动写sql语句代码在java中,这与ibatis的本质要将数据层的操作和业务逻辑操作分隔开来是违背的。其次,这个办法可能会被利用造成sql injection的问题。比如在sql语句的最后加上一句;drop some table。这样的结果显而易见,就是灾难性的。

2)用 Map
<select id=”checkLogin2″ parameterClass=”java.util.Map” resultClass=”java.lang.Integer”>
SELECT count(*) AS value FROM userinfo WHERE uid=#uid# and pwd=#pwd#
</select>

这种办法显得要清楚的很多,也不需要自己手动编写sql到java之中。
Map map=new HashMap();
map.put(”uid”, username);
map.put(”pwd”, password);
Integer r = (Integer) sqlMap.queryForObject(”checkLogin2″, map);

在java中首先生成需要的map,然后作为输入参数传入即可。这个方法应该是比较好的,值得推荐。

3)也有人采用根据需要编写javaBean的方法,但是这个方法的弊病在于如果你的逻辑操作涉及到很多的不同的属性的组合,你就会浪费很多资源去生成各种各样的bean。

iBatis学习记录(2)

今天主要对iBatis的各种SQL语句进行了一些测试,iBatis的query一共有三种形式,分别是queryForObject, queryForList, queryForMap

queryForObject返回的是一个一个单独的实例,queryForList返回的是一组实例,而queryForMap返回一个映射表

在使用这三个方法之前,首先需要在SqlMap文件中配置好相关的resultMap,这样才能将结果集顺利返回。也就是说,必须需要一个javaBean存在,然后是一个resultMap:

  1. # <resultMap id=“UserBeanMap” class=“com.featheast.chap4.UserBean”>
  2. # <result property=“id” column=“id”/>
  3. # <result property=“uid” column=“uid”/>
  4. # <result property=“pwd” column=“pwd”/>
  5. # <result property=“email” column=“email”/>
  6. # <result property=“name” column=“name”/>
  7. # <result property=“qq” column=“qq”/>
  8. # <result property=“year” column=“year”/>
  9. # <result property=“month” column=“month”/>
  10. # <result property=“day” column=“day”/>
  11. # </resultMap>

比如如上是一个UserBean的resultMap,它包含了这个bean中的所有的属性,并且对应到了数据库表中的列。

1).queryForObject:

代码看上去是很简单的,下面是按照ID取出唯一的一个user元素

如果你试图返回一个多行的值到Object中,程序就会报错Error: executeQueryForObject returned too many results

2).queryForList:

在前面的一篇文章中已经采用了queryForList来作为实验。其实看看第一部分的代码,需要改的地方其实就是把函数名改为queryForList,然后取出各个List就好了。道理是一样的。

3).queryForMap:

唯一需要改变的地方就是要讲resultMap中的class改换为java.util.HashMap,其余的都可以按照正常的方法向下进行,的确非常易懂。

2.insert:

相比较select的复杂而言,insert就简单的多了,几乎和jdbc中一样,直接套用上去就可以了。下面给出一个例子:

  1. <insert id=“insertUser”>
  2. INSERT INTO userinfo(
  3. uid,pwd,email,name,qq,year,month,day
  4. )VALUES(
  5. #uid:VARCHAR#,#pwd:VARCHAR#,#email:VARCHAR#,#name:VARCHAR#,#qq:VARCHAR#,#year:VARCHAR#,#month:VARCHAR#,#day:VARCHAR#
  6. )
  7. </insert>

以上是sql的map结果,是不是和JDBC一样呢。然后在JAVA中的调用:

  1. UserBean user=new UserBean();
  2. user.setDay(“31111″);
  3. user.setEmail(“featheast@123.com111″);
  4. user.setMonth(“10111″);
  5. user.setName(“featheast111″);
  6. user.setPwd(“123456111″);
  7. user.setQq(“30003000111″);
  8. user.setUid(“featheast111″);
  9. user.setYear(“2008111″);
  10. sqlMap.insert(“insertUser”,user);

如果觉得每次都得在sqlmap中写得太多而繁琐的话可以用一个parametermap来代替

  1. <parameterMap class=“com.featheast.chap4.UserBean” id=“insertUserMap”>
  2. <parameter property=“uid” jdbcType=“VARCHAR”/>
  3. <parameter property=“pwd” jdbcType=“VARCHAR”/>
  4. <parameter property=“email” jdbcType=“VARCHAR”/>
  5. <parameter property=“name” jdbcType=“VARCHAR”/>
  6. <parameter property=“qq” jdbcType=“VARCHAR”/>
  7. <parameter property=“year” jdbcType=“VARCHAR”/>
  8. <parameter property=“month” jdbcType=“VARCHAR”/>
  9. <parameter property=“day” jdbcType=“VARCHAR”/>
  10. </parameterMap>

如果你的数据库中有自动增长列那么就把那一列在添加的语句中空出来就可以了。系统会自动补上的。

iBatis学习记录(1)–转自以前的新浪博客

这一两个星期是学期结束的时候,也是各个项目交的时候,于是大忙特忙之下,人的身体状况也不佳。而且为了machine learning,还熬了在墨尔本的第一次夜。直到现在都还没怎么缓过来。还好,现在闲下来了,离考试时间还有三个星期,闲暇之余,去图书馆逛了逛,看到了这本崭新的iBatis in Action。很早就听说过这个持久层的框架,一般来说在你听说到Hibernate的时候,iBatis这个名字也会冒出来。一直都觉得 hibernate才是这一层里最有用的东西,就没有关心过太多iBatis,但这次看到了这本书,感觉上心动了一下,想想这几天也没什么事,书也不厚,就借回来看看好了。于是就这样开始了我的iBatis的学习路程。

目前看了前面的三章,用eclipse小试了一把,感觉这玩意的确很小巧实在。使用很容易,不用像其他的大型框架配置半天,它就只有一个jar,大小才376K,里面就包括了所有的东西了。这点是最吸引我的地方,毕竟小嘛,操作容易,上手也快。的确写起来很快,虽然我目前只做了一个很小的select的实验。对于真正的JAVA调用代码,其实就只有四行:

  1. try{
  2. String resource=“com/featheast/chap2/SqlMapConfig.xml”;
  3. Reader reader=Resources.getResourceAsReader(resource);
  4. SqlMapClient sqlMap=SqlMapClientBuilder.buildSqlMapClient(reader);
  5. List list=sqlMap.queryForList(“getAllUsers”,“1″);
  6. System.out.println(“Selected ”+list.size()+“ records.”);
  7. for(int i=0;i<list.size();i++){
  8. System.out.println(list.get(i));
  9. }
  10. }catch(Exception e){
  11. e.printStackTrace();
  12. }
  13. }

第一行是申明了你的sqlMapConfiguration文件的位置,第二行是读入这个配置文件,第三行是用这个文件生成sqlMap,最后一行就是调用其中的各种方法了。这样看来如果把配置文件给写好了的话,前面的JAVA简直就是太小儿科了。

回头来看看它的配置文件。分为两种,一种就是上面提到的sqlMapConfiguration,这是整个程序的全局配置地点。包括了你的数据库的驱动,地址,用户名,密码等等这些常用的connection参数:

  1. <sqlMapConfig>
  2. <properties resource=“com/featheast/chap2/db.properties”/>
  3. <transactionManager type=“JDBC”>
  4. <dataSource type=“SIMPLE”>
  5. <property name=“JDBC.Driver”
  6. value=“${driver}”/>
  7. <property name=“JDBC.ConnectionURL”
  8. value=“${url}”/>
  9. <property name=“JDBC.Username”
  10. value=“${user}”/>
  11. <property name=“JDBC.Password”
  12. value=“${password}”/>
  13. </dataSource>
  14. </transactionManager>
  15. <sqlMap resource=“com/featheast/chap2/SqlMap.xml”/>
  16. </sqlMapConfig>

上面这段代码就是一个简单的实例,其中的值是在properties文件中。可以看到非常直观易懂。如果你会JDBC,就没有什么好解释的了。如果你不懂,估计看了你也知道一二了。

接下来的关键部分就是上面这段代码中的sqlMap,这就是iBatis的核心部分,讲数据库的sql语句如何MAP到OO上来。

  1. <sqlMap>
  2. <select id=“getAllUsers” parameterClass=“string” resultClass=“hashmap”>
  3. SELECT * FROM userinfo WHERE month = #monthId#
  4. </select>
  5. </sqlMap>

看了以后也觉得非常的容易,不就是一个select语句被包在一个select的标签里吗。iBatis将sql语句划分为了input和output两部分,在上面这个语句中,你要输入的monthid就是input,得到的结果*就是output,返回的是一个hashmap。那么在java程序中就可以直接调用这些hashmap了。其实更好的是能够写出对应的返回值的bean,这样操作起来更加规范一些。

有一个小小的问题就是目前来说,这些XML配置文件的代码都得自己手写,于是这也就造成了会写错的地方,特别是DOCTYPE部分,下午我自己写的时候,就是在这里抄错了一个标点符号和多写了一个字母,结果BAIDU来GOOGLE去,都解决不了问题,最终还是发现了这点点的敲击键盘错误。要是以后eclipse能自动生成配置文件格式并检验就好了。我个人觉得现在应该也有了这种插件吧,还是明天再研究研究。

以上所列出的就是第一天学习的iBatis的一点点总结。很基础,每一个模块都还有很多东西要深究,这也就是后面几章要讲的内容。就我个人看来,iBatis相当于就是一个半自动化的ORM工具,毕竟各种SQL 语句还是得自己写,但是他能够将其MAP到OO,也算是一种很基础的封装,的确比直接调用JDBC显得要模式清楚的多。所以对于JDBC很熟悉的人来说,看这些东西真的是很容易的一件事。而且再次说的是,iBatis真的是小巧,和Hibernate比起来呵呵。不过自然hibernate有它的强大之处,打算等假期结束了,再重新回头来看一次Hibernate,也许会有更多的收货。

PS:iBatis还可以在.net上运行,现在是月底,网速没有了,明天到学校去下一个.net版本的跑跑C#看效果如何。

  • English Version

    • Cannot read Chinese? Please take a look at my English site, hope you can find more you need there!
  • 感谢支持

  • twitter

    facebook

    linkedin

    • You are currently browsing the archives for the iBatis category.

  • Categories