深入淺析Mybatis的缺陷問題
Mybatis是業(yè)界非常流行的持久層框架,輕量級(jí)、易用,在金融IT領(lǐng)域完全是領(lǐng)軍地位,比Hibernate更受歡迎,優(yōu)勢(shì)非常多,也是非常值得我們學(xué)習(xí)的。但Mybatis并不盡善盡美,其自身的設(shè)計(jì)、編碼也還有許多不足,甚至是缺陷,這篇文章來簡(jiǎn)要討論一下這些缺陷:
1.Mybatis使用DTD作為XML配置文件的校驗(yàn)文件,但是很明顯,DTD差不多是快被淘汰的技術(shù)了,功能非常有限,擴(kuò)展性非常差,擴(kuò)展性非常差,擴(kuò)展性非常差,可讀性也不好,Spring能夠從DTD到XSD華麗轉(zhuǎn)身,但Mybatis始終沒這個(gè)魄力。
2.版本兼容性做的不好,就拿3.3.0—>3.4.0來說,按業(yè)界通用規(guī)范,第2級(jí)版本號(hào)升級(jí),可以添加功能,但是要保證向下兼容性,然而Mybatis的做法并不完全是這樣的,看一下關(guān)鍵接口StatementHandler的關(guān)鍵方法prepare:
// 3.3.0 Statement prepare(Connection connection) throws SQLException; // 3.4.0 Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException;
這里沒有添加一個(gè)方法,而是直接在原方法中添加了一個(gè)參數(shù)!類似例子還有不少,就不一一列舉了。
3.Mybatis的插件,采用一個(gè)通用的Interceptor接口,配以@Intercepts、@Signature等注解,實(shí)現(xiàn)對(duì)多個(gè)組件的多種方法的攔截,看似非常靈活,在我看來其實(shí)是結(jié)構(gòu)不夠清晰,實(shí)際開發(fā)時(shí),你會(huì)把對(duì)StatementHandler和ResultSetHandler的攔截增強(qiáng)放在一個(gè)類里面嗎?不會(huì)是吧(會(huì)?你當(dāng)單一職責(zé)原則、開閉原則都是狗屎?jiǎn)幔?,那有什么必要?qiáng)制使用同一個(gè)接口呢?
另外,使用@Signature注解來設(shè)別需要被攔截的組件方法,如果注解有錯(cuò),編譯也是不會(huì)報(bào)錯(cuò)的,而只能等到運(yùn)行時(shí)才能發(fā)現(xiàn),再看上面的例子:
假設(shè)我針對(duì)3.3.0版本實(shí)現(xiàn)了一個(gè)插件:
@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) {
}
}
然后,升級(jí)為3.4.0,結(jié)果呢,編譯一直正常,但是等到運(yùn)行,卻拋出異常了。
4.Mybatis的緩存簡(jiǎn)直就是雞肋,而且不管有沒有配置需要使用緩存、是否更新緩存,都要去計(jì)算CacheKey,不使用緩存、也不更新緩存的情況下,這種計(jì)算完全是浪費(fèi)。
5.Mybatis的批量執(zhí)行,看下面的一個(gè)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, "數(shù)據(jù)" + random);//FIELD_NAME2
ps.setString(3, "參數(shù)" + random);//FIELD_NAME3
ps.addBatch();
}
int[] rs = ps.executeBatch();
}finally{
try{
ps.close();
}catch(Exception e){}
}
}
代碼沒有什么違和感,能夠執(zhí)行正常,也可以按預(yù)期的回滾,也就是說同一個(gè)事務(wù)中的同一個(gè)connection,可以同時(shí)運(yùn)行普通sql和batch,但是你在同一個(gè)事務(wù)的SqlSession中試試,反饋給你的是——不能在同一個(gè)事務(wù)中切換執(zhí)行方式!
6、數(shù)據(jù)庫(kù)產(chǎn)品的兼容性:Mybatis把SQL的控制權(quán)交給了開發(fā)人員,于是從道德上占據(jù)了制高點(diǎn)——你寫的不兼容,那是你自己的水平不行!但,這是一個(gè)真正的優(yōu)秀框架的正確姿勢(shì)嗎?為什么就不能提供一些輔助性的兼容實(shí)施?比如說在Oracle中被奉為神明的DECODE函數(shù),是否可以在SqlMapper中提供一個(gè)<decode>標(biāo)簽,在后面默默的修改成CASE WHEN?或者說,官方不提供沒有關(guān)系,但你得提供擴(kuò)展方式啊,于是又回到了:擴(kuò)展性非常差,擴(kuò)展性非常差,擴(kuò)展性非常差。重要的事說三遍,但,我已經(jīng)說六遍了。
以上所述是小編給大家介紹的Mybatis的缺陷問題,希望對(duì)大家有所幫助!
相關(guān)文章
MybatisPlus實(shí)現(xiàn)數(shù)據(jù)權(quán)限隔離的示例詳解
Mybatis Plus對(duì)Mybatis做了無侵入的增強(qiáng),非常的好用,今天就給大家介紹它的其中一個(gè)實(shí)用功能:數(shù)據(jù)權(quán)限插件,感興趣的可以跟隨小編一起了解下2024-04-04
JPA如何將查詢結(jié)果轉(zhuǎn)換為DTO對(duì)象
這篇文章主要介紹了JPA如何將查詢結(jié)果轉(zhuǎn)換為DTO對(duì)象,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
Java異常詳解_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
異常是Java語言中的一部分,它代表程序中由各種原因引起的“不正?!币蛩亍O旅嫱ㄟ^本文給大家介紹java異常的相關(guān)知識(shí),感興趣的朋友一起看看吧2017-06-06
Java中stream處理中map與flatMap的比較和使用案例
這篇文章主要介紹了Java中stream處理中map與flatMap的比較和使用案例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
通過Java實(shí)現(xiàn)自己動(dòng)手寫ls命令
在前面的文章中,我們仔細(xì)的介紹了關(guān)于ls命令的使用和輸出結(jié)果,在本篇文章當(dāng)中我們用Java代碼自己實(shí)現(xiàn)ls命令,更加深入的了解ls命令2022-10-10

