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的缺陷的更多相关文章

  1. mybatis 热部署xml文件(spring boot和springmvc两种方式)

    参考:http://thinkgem.iteye.com/blog/2304557 步骤:1.创建两个java类 (1)MapperRefresh.java   :用于刷新mapper (2)SqlS ...

  2. Mybatis学习之JDBC缺陷

    1.JDBC存在的问题 1.将sql语句硬编码到java代码中,如果修改sql语句,需要修改java代码,重新编译.系统可维护性不高. 设想如何解决?(将sql单独 配置在配置文件中) 2.数据库连接 ...

  3. Java EE开发平台随手记5——Mybatis动态代理接口方式的原生用法

    为了说明后续的Mybatis扩展,插播一篇广告,先来简要说明一下Mybatis的一种原生用法,不过先声明:下面说的只是Mybatis的其中一种用法,如需要更深入了解Mybatis,请参考官方文档,或者 ...

  4. MyBatis知多少(3)

    解决存储过程固有限制的方法之一就是将SQL嵌入到更加通用的语言中去.与存储过程将业务逻辑移入数据库相反,内联SQL将SQL从数据库移入了应用程序代码.这就使得SQL语句可以直接与语言进行交互.从某种意 ...

  5. MyBatis(4):动态SQL

    什么是动态SQL MyBatis的一个强大特性之一通常是它的动态SQL能力.如果你有使用JDBC或其他相似框架的经验,你就明白条件串联SQL字符串在一起是多么地痛苦,确保不能忘了空格或者在列表的最后的 ...

  6. mybatis通用DAO

    扫扫关注"茶爸爸"微信公众号 坚持最初的执着,从不曾有半点懈怠,为优秀而努力,为证明自己而活. 回复:茶爸爸了解他这个人!! 花了几天的时间研究了一下mybatis的源代码,觉得这 ...

  7. Mybatis(一) mybatis入门

    学习了hibernate这个持久层框架之后,在来学习Mybatis简直是无压力,因为Mybatis入门门栏很低,如果学习过了hibernate的话,对于Mybatis的学习很简单了,如果没学习过hib ...

  8. 从JDBC到hibernate再到mybatis之路

    一.传统的JDBC编程 在java开发中,以前都是通过JDBC(Java Data Base Connectivity)与数据库打交道的,至少在ORM(Object Relational Mappin ...

  9. Spring+SpringMVC+MyBatis+easyUI整合进阶篇(十一)redis密码设置、安全设置

    警惕 前一篇文章<Spring+SpringMVC+MyBatis+easyUI整合进阶篇(九)Linux下安装redis及redis的常用命令和操作>主要是一个简单的介绍,针对redis ...

随机推荐

  1. 3_for循环的拓展应用

    HTML代码: <input type="button" value="1"/> <input type="button" ...

  2. 使用OFBIZ 时,使用的键入提示。

    对商品的键入提示 ,效果如图(当输入关键字时,会提示出相应的数据) 首先要引入相应的插件 页面字段 js方法

  3. centos 6.X minimal 系列最小化安装完成后,安装mono和jexus过程小记录

    在使用虚拟机安装minimal版centos运行mono+jexus的时候,遇到了一些坑,记录一下,比如虚拟机访问不了网络,没wget命令没开放80端口,等等小问题,其他网上教程已经有mono+jex ...

  4. 基于AutoCAD的ObjectARX之NET扩展(mcnetarx)-AcdbEntGet

    1.AcdbEntGet用于获取实体的组码. 示例: ' 定义保存实体名称的变量 Dim ent() As Integer = New Integer() {} ' 获取最后一个实体 mcnetarx ...

  5. 套题 codeforces 360

    A题:Opponents 直接模拟 #include <bits/stdc++.h> using namespace std; ]; int main() { int n,k; while ...

  6. LintCode 366 Fibonacci

    /* 1st method will lead to time limit *//* the time complexity is exponential sicne T(n) = T(n-1) + ...

  7. JAVA使用POI操作excel

    文中处理的excel是2003年以前的版本,使用HSSFworkbook,如果处理2007版本以后的excel,用XSSFworkbook,对于二者的兼容性问题,可参考 http://blog.csd ...

  8. String、String.valueOf、toString 它们三者的区别总结

    今天在使用这个的时候发现,他们三者好像在某些场所都是可以用的,但是不免会让人想到那既然它们三者这么的相似,那么总有些什么区别吧.我也在网上找了一些资料看.自己也看了API文档,就将他们三的区别总结一下 ...

  9. 从KRE到XRE:ASP.NET 5中正在消失的那些K

    前几天写了篇博客ASP.NET 5中的那些K,刚把ASP.NET 5中的那些K搞明白了些,昨天发现微软正在让那些K消失. 首先是在 KRuntime 的git日志中发现的: * Runtime ren ...

  10. PowerShell笔记

    教程: http://www.pstips.net/powershell-online-tutorials/ http://www.3fwork.com/a113/ 1. 查看成员 $MyInvoca ...