English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Mybatisの欠点と問題の深い分析

Mybatisは業界で非常に人気のある持久層フレームワークであり、軽量で使いやすいです。金融IT分野では完全にリーダー的な地位を占めており、Hibernateよりも人気があり、非常に多くの利点があります。また、非常に学ぶ価値があります。しかし、Mybatisは完璧ではありません。その設計やコーディングには多くの欠点や欠陥もあります。この記事では、これらの欠陥について簡単に議論します:

1MybatisはXML設定ファイルの検証ファイルとしてDTDを使用していますが、明らかにDTDは廃止される技術に近づいています。機能は限られており、拡張性が非常に悪く、可読性も悪いです。SpringはDTDからXSDに美しく変身できますが、Mybatisはこの勇気を持っていません。

2バージョン互換性がよくない、例えば3.3バージョン0.0から3.4バージョン0.0において、業界標準に従って、2バージョンアップにより、機能を追加できますが、下位互換性を確保する必要があります。しかし、Mybatisの方法は完全にこれとは異なります。重要なインターフェースStatementHandlerの重要なメソッドprepareを見てみましょう:

// 3.3バージョン0.0
Statement prepare(Connection connection)
throws SQLException;
// 3.4バージョン0.0
Statement prepare(Connection connection, Integer transactionTimeout)
throws SQLException;

ここでは、メソッドに新しいパラメータを追加するのではなく、元のメソッドに直接パラメータを追加しています!このような例は他にもたくさんありますが、一つずつ挙げるのは面倒です。

3バージョン0.0のMybatisプラグインは、一般的なInterceptorインターフェースを使用し、@Intercepts、@Signatureなどのアノテーションを用いて、複数のコンポーネントの複数のメソッドのインターセプトを実現します。見た目は非常に柔軟ですが、実際には構造が明確でないと感じます。実際の開発では、StatementHandlerとResultSetHandlerのインターセプトを強制的に同じクラスにまとめる必要がありますか?それはありませんでしょう(ありますか?あなたは単一責任原則、オープンカプセル化原則がゴミだと思っていますか?)。それでは、同じインターフェースを使用する必要がある理由は何ですか?

また、@Signatureアノテーションを使用して、インターセプトする必要があるコンポーネントメソッドを設定します。アノテーションにエラーがあれば、コンパイルエラーは報告されません。その代わりに、実行時までに発見されます。上記の例を見てみましょう:

仮に以下の3.3バージョン0.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_NAME"1 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_NAME"2(FIELD_NAME}}1, 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に変更することはできますか?または、公式が提供しなくてもかまいませんが、拡張方法を提供する必要があります。そして、再び拡張性が非常に悪いという結論に至ります。重要なことを何度も言いますが、私はすでに6回言っています。

以下は、編集者が皆さんに紹介するMybatisの欠点と問題点です。皆さんに役立つことを願っています!

基本教程
おすすめ