Mybatis的缺陷,Mybatis缺陷

來源:互聯網
上載者:User

Mybatis的缺陷,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.0Statement prepare(Connection connection)      throws SQLException;// 3.4.0Statement 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?或者說,官方不提供沒有關係,但你得提供擴充方式啊,於是又回到了:擴充性非常差,擴充性非常差,擴充性非常差。重要的事說三遍,但,我已經說六遍了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.