1、基本信息不同
mybatis:MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。
ibatis:iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO),同时还提供一个利用这个框架开发的JPetStore实例。相对Hibernate和ApacheOJB等“一站式”ORM解决方案而言,ibatis 是一种“半自动化”的ORM实现。
iBATIS 目前提供了三种语言实现的版本,包括:Java、.NET以及Ruby。
2、开发时间不同
mybatis:MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。
ibatis:iBATIS一词来源于“internet”和“abatis”的组合,是一个由Clinton Begin在2001年发起的开放源代码项目。
3、配置方法不同
mybatis简化了编码的过程,不需要去写dao的实现类,直接写一个dao的接口,再写一个xml配置文件,整个mybatis就配置好了,也就是数据库就连接好了,然后在service里面直接调用dao就可以了,但是ibatis则不可以,必须要写dao的实现类。mybatis是ibatis的升级版本。
参考资料:百度百科-mybatis。
参考资料:百度百科-ibatis。
iBATIS一词来源于“internet”和“abatis”的组合,是一个由Clinton Begin在2002年发起的开放源代码项目。于2010年6月16号被谷歌托管,改名为MyBatis。是一个基于SQL映射支持Java和·NET的持久层框架。
在ibatis中,parameterClass的类型大都是:string,int/对象/hashmap\x0d\x0aresultclass/resultMap的类型大都是:对象/hashmap\x0d\x0a当parameterClass为string,int时,可用#value#表示或直接用传入的值名表示。\x0d\x0a当parameterClass/resultMap的类型是对象时,用#属性#表示。程序会调用JAVABEAN的getter方法,进行获取属性值。\x0d\x0a当parameterClass/resultMap的类型是hashmap(Map是key-value结构的)时,那程序会直接通过key来分析取参数。\x0d\x0a\x0d\x0a具体请见以下两部分:\x0d\x0aibatis各种参数数据集\x0d\x0a原型参数 \x0d\x0a\x0d\x0a select\x0d\x0a ID as id,\x0d\x0a TYPE as type,\x0d\x0a DESCR as descr\x0d\x0a from APP_LOG\x0d\x0a where ID = #id#\x0d\x0a \x0d\x0asqlMapper.queryForObject("select0", id);\x0d\x0a参数名与传入值名称一样,应该也可用参数#value#表示。
ibatis
是数据持久层,对应.NET方向的有ibatis.NET,只要用来处理数据库表结构和程序实体之间映射,ado.net是用来处理和数据库直接通信的,取出数据(object,int,string,dataset,datatable等常规类型),通常程序中如果用到MODEL实体,都需要手动写代码去做类型转换(把datatable的字段值赋值到model对应字段),用了数据持久层,这一部就可以省略了,ibatis.NET可以直接把数据库表字段映射为实体模型,操作简便了。
问题总结:
1.index by表不能存储在数据库中的type中,故选择嵌套表。
2.ibatis不支持oracle的复合数据类型的返回。(个人理解)
3.替代方案:用返回oracle游标来代替复合数据类型。ibatis能接受oracle游标类型。
注意此处是ibatis2.3
部分代码:
1.java
复制代码
1 private Map<String,Object> userStateResult(Users users)throws Exception{。
2 Map<String,Object> param = new HashMap<String,Object>();。
3 param.put("PRM_USERID", users.getUserid().toString());。
4 param.put("PRM_OBJECTS", null);。
5 param.put("PRM_TAGS", null);。
6 param.put("PRM_APPCODE", null);。
7 param.put("PRM_ERRMSG", null);。
8 getDao().queryForList("user.prc_user_index",param);。
9 if(Constant.SUCCESS.equals(param.get("PRM_APPCODE"))){。
10 return param;。
11 }else{
12 return null;。
13 }
14 }
复制代码
返回值(包括游标的返回值)都在param这个map中。
2.ibatis代码:
复制代码
1 <parameterMap class="java.util.Map" id="UserIndexParam">。
2 <parameter property="PRM_USERID" javaType="java.lang.String"。
3 jdbcType="VARCHAR" mode="IN" />。
4 <parameter property="PRM_OBJECTS" javaType="java.sql.ResultSet"。
5 jdbcType="ORACLECURSOR" mode="OUT" resultMap="ref_object" />。
6 <parameter property="PRM_TAGS" javaType="java.sql.ResultSet"。
7 jdbcType="ORACLECURSOR" mode="OUT" resultMap="ref_tag" />。
8 <parameter property="PRM_APPCODE" javaType="java.lang.String"。
9 jdbcType="VARCHAR" mode="OUT" />。
10 <parameter property="PRM_ERRMSG" javaType="java.lang.String"。
11 jdbcType="VARCHAR" mode="OUT" />。
12 </parameterMap>。
13 ---------------------------------------------------------------------------------。
14 <resultMap id="ref_tag" class="com.diy.tag.entity.Tag">。
15 <result column="tagid" jdbcType="VARCHAR" property="tagid" />。
16 <result column="tagname" jdbcType="VARCHAR" property="name" />。
17 </resultMap>。
18
19 <resultMap class="com.diy.comm.cursorHandler.ObjectHandler" id="ref_object">。
20 <result column="OBJECTID" jdbcType="DECIMAL" property="objectid" />。
21 <result column="OWNERID" jdbcType="DECIMAL" property="ownerid" />。
22 <result column="DBUSID" jdbcType="DECIMAL" property="dbusid" />。
23 <result column="DUSERSID" jdbcType="DECIMAL" property="dusersid" />。
24 <result column="TAGID" jdbcType="VARCHAR" property="tagid" />。
25 <result column="USERNAME" jdbcType="VARCHAR" property="username" />。
26 <result column="OBJNAME" jdbcType="VARCHAR" property="objname" />。
27 <result column="LOVENUM" jdbcType="DECIMAL" property="lovenum" />。
28 <result column="INRUDUCTION" jdbcType="VARCHAR" property="inruduction" />。
29 <result column="CATAGROY" jdbcType="DECIMAL" property="catagroy" />。
30 <result column="IMAGEPATH" jdbcType="VARCHAR" property="imagepath" />。
31 </resultMap>。
32 ---------------------------------------------------------------------------。
33 <procedure id="prc_user_index" parameterMap="UserIndexParam">。
34 {call。
35 PKG_USER.PRC_USER_INDEXVIEW(?,?,?,?,?)}。
36 </procedure>。
复制代码
有一篇文章写的很好:大家可以参考一下http://blog.sina.com.cn/s/blog_80c111410100vgsh.html。
但是对于本问题没有用ibatis的TypeHandler。
因为存储过程调试可以返回游标数据,但是ibatis接受的到全部是null。不知道原因,有知道的朋友可以留言一下。
我个人猜测可能是ibatis版本问题。
3.存储过程代码(部分):
复制代码
--对象类型
CREATE OR REPLACE TYPE TAGS_INFO IS object。
TAGID number,。
TAGNAME varchar2(200)。
--嵌套表
CREATE OR REPLACE TYPE table_tag IS TABLE OF TAGS_INFO。
注意对象和嵌套表都要放在全局的。不能定义在包体中。
--兴趣游标
TYPE TAGCURSOR IS REF CURSOR;。
--东西游标
TYPE OBJECTCURSOR IS REF CURSOR;--这个定义在包体中。
------------------------------------------------------------------------。
PROCEDURE PRC_USER_INDEXVIEW(PRM_USERID IN VARCHAR2,。
PRM_OBJECTS OUT OBJECTCURSOR,。
PRM_TAGS OUT TAGCURSOR,。
PRM_APPCODE OUT VARCHAR2,。
PRM_ERRMSG OUT VARCHAR2) IS。
N_FLAG NUMBER;。
VAR_FIRSTTAG VARCHAR2(100);。
VAR_DUSERID VARCHAR2(100);。
INDEX_TAGS TABLE_TAG;。
--用户兴趣标签
CURSOR CUR_USERTAG IS。
SELECT C.TAGID, C.NAME。
FROM USERSDETIAL A, TAGRELATION B, TAG C。
WHERE A.DUSERSID = B.DUSERSID。
AND B.TAGID = C.TAGID。
AND A.DUSERSID = VAR_DUSERID;。
--公共兴趣标签
CURSOR CUR_USERPUB IS。
SELECT T.*。
FROM (SELECT ROWNUM AS RNUM,。
COUNT(A.DUSERSID) AS CNUM,。
B.TAGID,。
B.NAME。
FROM TAGRELATION A, TAG B。
WHERE A.TAGID = B.TAGID。
GROUP BY A.DUSERSID, B.TAGID, B.NAME, ROWNUM) T。
WHERE RNUM <= 8。
ORDER BY T.CNUM DESC;。
--object
/*CURSOR CUR_OBJ(VAR_TAGID VARCHAR2) IS。
SELECT ROWNUM AS RN, A.*。
FROM OBJECT A。
WHERE trim(A.TAGID) = VAR_TAGID。
AND ROWNUM < 30;*/。
REC_USERTAG CUR_USERTAG%ROWTYPE;。
REC_USERPUB CUR_USERPUB%ROWTYPE;。
--REC_OBJ OBJECT%ROWTYPE;。
BEGIN
PRM_APPCODE := PKG_COMM.DEF_OK;。
PRM_ERRMSG := '';。
IF PRM_USERID IS NULL THEN。
PRM_APPCODE := PKG_COMM.DEF_ERR;。
PRM_ERRMSG := '参数未定义';。
RETURN;
END IF;
--用户详细ID是否存在。
SELECT B.DUSERSID。
INTO VAR_DUSERID。
FROM USERS A, USERSDETIAL B。
WHERE A.USERID = B.USERSID。
AND A.USERID = PRM_USERID;。
IF VAR_DUSERID IS NULL THEN。
PRM_APPCODE := PKG_COMM.DEF_ERR;。
PRM_ERRMSG := '参数无效';。
RETURN;
END IF;
--1.判断是否为有效用户。
SELECT NVL(A.FLAG, 1)。
INTO N_FLAG。
FROM USERS A, USERSDETIAL B。
WHERE A.USERID = B.USERSID。
AND B.DUSERSID = VAR_DUSERID;。
IF N_FLAG = 1 THEN。
PRM_APPCODE := PKG_COMM.DEF_ERR;。
PRM_ERRMSG := '用户已被禁止登录';。
RETURN;
END IF;
--2.判断用户是否有兴趣tag。
FOR REC_USERTAG IN CUR_USERTAG LOOP。
INDEX_TAGS := TABLE_TAG();。
IF CUR_USERTAG%ROWCOUNT = 0 THEN。
--获取公共兴趣游标。
FOR REC_USERPUB IN CUR_USERPUB LOOP。
INDEX_TAGS.EXTEND;。
IF CUR_USERPUB%ROWCOUNT = 1 THEN。
VAR_FIRSTTAG := REC_USERPUB.TAGID;。
END IF;。
INDEX_TAGS(CUR_USERPUB%ROWCOUNT) := TAGS_INFO(REC_USERPUB.TAGID,。
REC_USERPUB.NAME);。
END LOOP;。
ELSIF CUR_USERTAG%ROWCOUNT = 1 THEN。
VAR_FIRSTTAG := REC_USERTAG.TAGID;。
END IF;
INDEX_TAGS.EXTEND;。
INDEX_TAGS(CUR_USERTAG%ROWCOUNT) := TAGS_INFO(REC_USERTAG.TAGID,。
REC_USERTAG.NAME);。
--index_tags(CUR_USERTAG%ROWCOUNT).TAGNAME := REC_USERTAG.NAME;。
END LOOP;
IF INDEX_TAGS.COUNT <> 0 THEN。
/* --3. 取出object。
FOR REC_OBJ IN CUR_OBJ(VAR_FIRSTTAG) LOOP。
PRM_OBJECTS(CUR_OBJ%ROWCOUNT).OWNERID := REC_OBJ.OWNERID;。
PRM_OBJECTS(CUR_OBJ%ROWCOUNT).OBJECTID := REC_OBJ.OBJECTID;。
PRM_OBJECTS(CUR_OBJ%ROWCOUNT).DBUSID := REC_OBJ.DBUSID;。
PRM_OBJECTS(CUR_OBJ%ROWCOUNT).DUSERSID := REC_OBJ.DUSERSID;。
PRM_OBJECTS(CUR_OBJ%ROWCOUNT).TAGID := REC_OBJ.TAGID;。
PRM_OBJECTS(CUR_OBJ%ROWCOUNT).LOVENUM := REC_OBJ.LOVENUM;。
PRM_OBJECTS(CUR_OBJ%ROWCOUNT).INRUDUCTION := REC_OBJ.INRUDUCTION;。
PRM_OBJECTS(CUR_OBJ%ROWCOUNT).CATAGROY := REC_OBJ.CATAGROY;。
PRM_OBJECTS(CUR_OBJ%ROWCOUNT).Imagepath := REC_OBJ.Imagepath;。
END LOOP;*/。
--返回东西游标
OPEN PRM_OBJECTS FOR。
SELECT ROWNUM AS RN, A.*, B.USERNAME。
FROM OBJECT A, USERSDETIAL B。
WHERE A.OWNERID = B.DUSERSID。
AND TRIM(A.TAGID) = VAR_FIRSTTAG。
AND ROWNUM < 30;。
END IF;
--tag游标
OPEN PRM_TAGS FOR。
SELECT * FROM TABLE(CAST(INDEX_TAGS AS TABLE_TAG));。
EXCEPTION
WHEN OTHERS THEN。
PRM_APPCODE := PKG_COMM.DEF_ERR;。
PRM_ERRMSG := '获取主界面数据失败' || '错误原因:' || PRM_ERRMSG || '-' || SQLERRM ||。
'错误行数:' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE();。
END;
---注意:a.返回游标的用open for 方法,不用关心游标的关闭。它是自动关闭的。原因:调试把游标返回值点几下,你就回发现。
b.如果报错CURSOR IS CLOESD的话,说明游标里面没有数据。所以open for 必须保证有select中有数据。
c.嵌套表这里要用类似与java的构造方法写,如上。
如果写成类似于java中new对象后,用set方法给嵌套表赋值的,会报错未能未能初始化的结果集。