锁定老帖子 主题:ibatis/Mybatis实战分享与讨论
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-12-20
最后修改:2011-12-20
关于ibatis入门如何? 入门相对容易,好像没什么有他官方上那本pdf更好的,而且有中文版,看起来速度刷刷的 ibatis主要提供了什么? 数据库字段到model映射,这个通过强大的xml配置解决,可以做出类似hibernate的效果,但是sql语句是你自己书写,也没有面向对象建立数据库的压力,又比spring jdbc之类强大 模板配置sql到底多强大? 可以动态配置sql,可以使用ognl表达式,你的sql用广告词,叫做会跳舞的sql,以前看帖子,有哥们说他们项目自己该造,用freemarker搭建了一个模板,很强大,到底有那些好处,具体不太了解,我觉得现在的绝对够用,就是配置有些繁琐 比如我们ognl严重 <where> <if test="@Ognl@isNotEmpty(clickId)"> AND click_id = #{clickId} </if> </where> public class Ognl { /** * 可以用于判断String,Map,Collection,Array是否为空 * @param o * @return */ public static boolean isEmpty(Object o) throws IllegalArgumentException { if(o == null) return true; if(o instanceof String) { if(((String)o).length() == 0){ return true; } } else if(o instanceof Collection) { if(((Collection)o).isEmpty()){ return true; } } else if(o.getClass().isArray()) { if(Array.getLength(o) == 0){ return true; } } else if(o instanceof Map) { if(((Map)o).isEmpty()){ return true; } }else { return false; // throw new IllegalArgumentException("Illegal argument type,must be : Map,Collection,Array,String. but was:"+o.getClass()); } return false; } /** * 可以用于判断 Map,Collection,String,Array是否不为空 * @param c * @return */ public static boolean isNotEmpty(Object o) { return !isEmpty(o); } public static boolean isNotBlank(Object o) { return !isBlank(o); } ...略 ibatis这些点怎么搭建一个良好快速的开发环境呢?(也就是对ibatis提供的特性进行了强力的封装) 1.代码生成器需要统一的几个点 利用代码生成器,我们每张表的常规操作,CRUD于基于简单字段查询条件的分页都自动生成映射到model上了 统一了几个点:namespace=table.xxx xxx代表具体操作,每张表生成适合都是统一的 也自动生成了action--service--dao--xml 2.底层统一接口调用的问题 Dao层继承BaseIbatisDao,上面统一的几个点造成了一些Crud于有条件的分页可以放到顶层的Dao中 不可能每次调用都要打开sqlsession 关闭sqlsession 那么模板方法模式封装好这个流程,然后每次调用就可以了,每次直接调用模板sqlsessionTemplete 类似模板方法: public Object execute(SqlSessionCallback action) { SqlSession session = null; try { session = sqlSessionFactory.openSession(); Object result = action.doInSession(session); return result; }finally { if(session != null) session.close(); } } public Object executeBatch(SqlSessionCallback action) { SqlSession session = null; try { session = sqlSessionFactory.openSession(false); Object result = action.doInSession(session); return result; }finally { if(session != null) { session.commit(true); session.close(); } } } 3.分页问题解决 这个没想象那么难,见下面模板跟代码 <select id="AdClickinfo.findPage" resultMap="RM.AdClickinfo"> SELECT <include refid="AdClickinfo.columns" /> FROM ad_clickinfo <include refid="AdClickinfo.findPage.where"/> <if test="@Ognl@isNotEmpty(sortColumns)"> ORDER BY ${sortColumns} </if> </select> <sql id="AdClickinfo.findPage.where"> <!-- ognl访问静态方法的表达式 为@class@method(args),以下为调用rapid中的Ognl.isNotEmpty()方法,还有其它方法如isNotBlank()可以使用,具体请查看Ognl类 --> <where> <if test="@Ognl@isNotEmpty(clickId)"> AND click_id = #{clickId} </if> <if test="@Ognl@isNotEmpty(adId)"> AND ad_id = #{adId} </if> <if test="@Ognl@isNotEmpty(clickDatetimeBegin)"> AND click_datetime >= #{clickDatetimeBegin} </if> <if test="@Ognl@isNotEmpty(clickDatetimeEnd)"> AND click_datetime <= #{clickDatetimeEnd} </if> <if test="@Ognl@isNotEmpty(clickIp)"> AND click_ip = #{clickIp} </if> <if test="@Ognl@isNotEmpty(clickFrom)"> AND click_from = #{clickFrom} </if> </where> </sql> public static Page pageQuery(SqlSessionTemplate sqlSessionTemplate,String statementName,String countStatementName, PageRequest pageRequest) { Number totalCount = (Number) sqlSessionTemplate.selectOne(countStatementName,pageRequest); if(totalCount == null || totalCount.longValue() <= 0) { return new Page(pageRequest,0); } Page page = new Page(pageRequest,totalCount.intValue()); Map filters = new HashMap(); filters.put("offset", page.getFirstResult()); filters.put("pageSize", page.getPageSize()); filters.put("lastRows", page.getFirstResult() + page.getPageSize()); filters.put("sortColumns", pageRequest.getSortColumns()); Map parameterObject = PropertyUtils.describe(pageRequest); filters.putAll(parameterObject); List list = sqlSessionTemplate.selectList(statementName, filters,page.getFirstResult(),page.getPageSize()); page.setResult(list); return page; } public class Page<T> implements Serializable,Iterable<T> { protected List<T> result; protected int pageSize; protected int pageNumber; protected int totalCount = 0; public Page(PageRequest p, int totalCount) { this(p.getPageNumber(),p.getPageSize(),totalCount); } public Page(int pageNumber,int pageSize,int totalCount) { this(pageNumber,pageSize,totalCount,new ArrayList(0)); } public Page(int pageNumber,int pageSize,int totalCount,List<T> result) { if(pageSize <= 0) throw new IllegalArgumentException("[pageSize] must great than zero"); this.pageSize = pageSize; this.pageNumber = PageUtils.computePageNumber(pageNumber,pageSize,totalCount); this.totalCount = totalCount; setResult(result); } 实际使用遇到的问题 1.关于灵活性的问题 你需要model中的几个属性值,你是调用自动生成的代码取得整个model,还是自己写一个,如果这个查询发生次数多,必须自己写 2.关于配置复杂的问题 看下官方文档高级映射,就知道这个难度不大,写着麻烦,配置很繁琐,为了一个特殊的查询是否有必要取那样做,前后端都hashmap,跨过model映射这个,如果要自己写,你的model要符合,我们的model不满足,全部直接都hashmap 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-12-21
总结的不错 但是没有一个很明确的流程 能给一个样例就好了 我用MyBatis 自己也封装过分页
|
|
返回顶楼 | |
发表时间:2011-12-21
"@Ognl 我用这个时报错 。。。 他奶奶的
|
|
返回顶楼 | |
发表时间:2011-12-22
“互联网项目”Hibernate有啥不可以。。。
|
|
返回顶楼 | |
发表时间:2011-12-22
不太喜欢mybatis。封装的太深,有个问题还难定位。mybatis优势就是sql写在配置文件中。用spring jdbc+freemarker一样能够做到这样的,而且简洁
|
|
返回顶楼 | |
发表时间:2011-12-22
最后修改:2011-12-22
引用 用代码生成器,我们每张表的常规操作,CRUD于基于简单字段查询条件的分页都自动生成映射到model上了
统一了几个点:namespace=table.xxx xxx代表具体操作,每张表生成适合都是统一的 也自动生成了action--service--dao--xml 我们现在也生成了service--dao--xml,但是我总是用的不爽,限制的死死的 现在复杂查询采用N+1方式 以前有位仁兄的文章说不一定慢,没有实测过 我觉得service还是自己写好一点 |
|
返回顶楼 | |
发表时间:2011-12-22
最后修改:2011-12-22
melin 写道 不太喜欢mybatis。封装的太深,有个问题还难定位。mybatis优势就是sql写在配置文件中。用spring jdbc+freemarker一样能够做到这样的,而且简洁
确实是sql写在配置文件是唯一优势,但是spring jdbc+freemaker要得到mybatis的效果有点难,你们具体是怎么做,动态sql这块,返回值这个映射? 很感兴趣啊,能给讲讲吗? |
|
返回顶楼 | |
发表时间:2011-12-22
melin 写道 不太喜欢mybatis。封装的太深,有个问题还难定位。mybatis优势就是sql写在配置文件中。用spring jdbc+freemarker一样能够做到这样的,而且简洁
我也是这么认为,找个空指针异常都没法定位,只能靠经验了 |
|
返回顶楼 | |
发表时间:2011-12-22
Brera 写道 引用 用代码生成器,我们每张表的常规操作,CRUD于基于简单字段查询条件的分页都自动生成映射到model上了
统一了几个点:namespace=table.xxx xxx代表具体操作,每张表生成适合都是统一的 也自动生成了action--service--dao--xml 我们现在也生成了service--dao--xml,但是我总是用的不爽,限制的死死的 现在复杂查询采用N+1方式 以前有位仁兄的文章说不一定慢,没有实测过 我觉得service还是自己写好一点 为什么service不能自己写?自动生成的只是基本的CRUD+分页 负责查询用n+1具体是什么情况,是数据量的问题导致必须延迟加载才n+1的必要,还是什么 |
|
返回顶楼 | |
发表时间:2011-12-22
Mybatis的generator+plugin,完成DAO+model封装,搞定单表curd+翻页
service用Criteria的方式拼装条件,多表连接在service实现,有cache的情况下,性能会更好。 把逻辑放到service层比放到sql里好太多,各种血的教训。 |
|
返回顶楼 | |