深入浅析Mybatis的缺陷问题
mybatis是业界非常流行的持久层框架,轻量级、易用,在金融it领域完全是领军地位,比hibernate更受欢迎,优势非常多,也是非常值得我们学习的。但mybatis并不尽善尽美,其自身的设计、编码也还有许多不足,甚至是缺陷,这篇文章来简要讨论一下这些缺陷:
1.mybatis使用dtd作为xml配置文件的校验文件,但是很明显,dtd差不多是快被淘汰的技术了,功能非常有限,扩展性非常差,扩展性非常差,扩展性非常差,可读性也不好,spring能够从dtd到xsd华丽转身,但mybatis始终没这个魄力。
2.版本兼容性做的不好,就拿3.3.0—>3.4.0来说,按业界通用规范,第2级版本号升级,可以添加功能,但是要保证向下兼容性,然而mybatis的做法并不完全是这样的,看一下关键接口statementhandler的关键方法prepare:
// 3.3.0 statement prepare(connection connection) throws sqlexception; // 3.4.0 statement prepare(connection connection, integer transactiontimeout) throws sqlexception;
这里没有添加一个方法,而是直接在原方法中添加了一个参数!类似例子还有不少,就不一一列举了。
3.mybatis的插件,采用一个通用的interceptor接口,配以@intercepts、@signature等注解,实现对多个组件的多种方法的拦截,看似非常灵活,在我看来其实是结构不够清晰,实际开发时,你会把对statementhandler和resultsethandler的拦截增强放在一个类里面吗?不会是吧(会?你当单一职责原则、开闭原则都是*吗),那有什么必要强制使用同一个接口呢?
另外,使用@signature注解来设别需要被拦截的组件方法,如果注解有错,编译也是不会报错的,而只能等到运行时才能发现,再看上面的例子:
假设我针对3.3.0版本实现了一个插件:
@intercepts({ @signature(type = statementhandler.class, method = "prepare", args = {connection.class }) }) public class statementhandlerinterceptor implements interceptor { @override public object intercept(invocation invocation) throws throwable { return invocation.proceed(); } @override public object plugin(object target) { return plugin.wrap(target, this); } @override public void setproperties(properties properties) { } }
然后,升级为3.4.0,结果呢,编译一直正常,但是等到运行,却抛出异常了。
4.mybatis的缓存简直就是鸡肋,而且不管有没有配置需要使用缓存、是否更新缓存,都要去计算cachekey,不使用缓存、也不更新缓存的情况下,这种计算完全是浪费。
5.mybatis的批量执行,看下面的一个jdbc例子:
public void testjdbcbatch(connection conn) throws exception {try{ conn.setautocommit(false); batchupdate(conn); cleartestdata(conn); conn.commit(); conn.setautocommit(true); }catch(exception e){ conn.rollback(); throw e; } } private void cleartestdata(connection conn) throws sqlexception { preparedstatement ps = null; try{ ps = conn.preparestatement("delete table_name1 where field_name1 = ? "); ps.setstring(1, "test"); int d = ps.executeupdate(); system.out.println("delete counts : " + d); }finally{ try{ ps.close(); }catch(exception e){} } } private void batchupdate(connection conn) throws sqlexception { preparedstatement ps = null; try{ string sql = "insert into table_name2(field_name1, field_name2, field_name2)values(?,?,?)"; ps = conn.preparestatement(sql); for(int i = 0; i < 10; i++){ string random = randomstringutils.randomalphabetic(8); ps.setstring(1, "test");//field_name1 ps.setstring(2, "数据" + random);//field_name2 ps.setstring(3, "参数" + random);//field_name3 ps.addbatch(); } int[] rs = ps.executebatch(); }finally{ try{ ps.close(); }catch(exception e){} } }
代码没有什么违和感,能够执行正常,也可以按预期的回滚,也就是说同一个事务中的同一个connection,可以同时运行普通sql和batch,但是你在同一个事务的sqlsession中试试,反馈给你的是——不能在同一个事务中切换执行方式!
6、数据库产品的兼容性:mybatis把sql的控制权交给了开发人员,于是从道德上占据了制高点——你写的不兼容,那是你自己的水平不行!但,这是一个真正的优秀框架的正确姿势吗?为什么就不能提供一些辅助性的兼容实施?比如说在oracle中被奉为神明的decode函数,是否可以在sqlmapper中提供一个<decode>标签,在后面默默的修改成case when?或者说,官方不提供没有关系,但你得提供扩展方式啊,于是又回到了:扩展性非常差,扩展性非常差,扩展性非常差。重要的事说三遍,但,我已经说六遍了。
以上所述是小编给大家介绍的mybatis的缺陷问题,希望对大家有所帮助!
上一篇: 轻松掌握Java代理模式
推荐阅读
-
深入浅析Mybatis的缺陷问题
-
详解Mybatis逆向工程中使用Mysql8.0版本驱动遇到的问题
-
深入浅析SSH的三个组件ssh、sftp、scp
-
Spring+SpringMVC+MyBatis深入学习及搭建(一)之MyBatis的基础知识
-
浅析一个MYSQL语法(在查询中使用count)的兼容性问题
-
深入理解MyBatis中的一级缓存与二级缓存
-
工作中遇到的mysql+mybatis的问题小结 博客分类: mysql
-
SSM框架整合遇到的问题汇总(Spring+SpringMVC+Mybatis+PostgreSQL+Tomcat7+Maven)v.18
-
解决mybatis一对多查询问题时的只显示一条数据的问题(查询部门的同时把所属部门的员工信息查出来)关联查询
-
mysql字段默认值不生效的问题解决(上) 博客分类: mybatis mysqlmybatisibatisinsert默认值