English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
MyBatis é uma das frameworks de persistência mais populares na indústria, leve e fácil de usar, ocupando uma posição de liderança completa no campo do IT financeiro, mais popular que o Hibernate, com muitos pontos fortes e muito digno de aprendizado. Mas o MyBatis não é perfeito, e seu próprio design e codificação ainda têm muitas deficiências, até mesmo falhas. Este artigo discutirá brevemente essas falhas:
1.Mybatis usa DTD como arquivo de validação de configuração XML, mas é claro que DTD está prestes a ser descontinuada, com funcionalidades muito limitadas, escalabilidade muito ruim, escalabilidade muito ruim, escalabilidade muito ruim, e também com baixa leitura, a Spring pode fazer uma transição brilhante de DTD para XSD, mas Mybatis nunca teve essa coragem.
2.compatibilidade não foi bem feita, pegue3.3.0—>3.4.0, conforme o padrão comum da indústria, o2Versão de nível de versão pode adicionar funcionalidades, mas deve garantir a compatibilidade para baixo, contudo, a abordagem da Mybatis não é completamente assim, veja o método crucial prepare da interface StatementHandler:
// 3.3.0 Statement prepare(Connection connection) throws SQLException; // 3.4.0 Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException;
Aqui não foi adicionado um método, mas foi adicionado um parâmetro diretamente no método original! Existem muitos exemplos semelhantes, não vou列举 um a um.
3.Mybatis plugins, usam uma interface Interceptor genérica, combinada com anotações como @Intercepts, @Signature, etc., para interceptar vários métodos de vários componentes, parece muito flexível, mas na minha opinião, a estrutura não é clara o suficiente, na verdade, você colocaria o interceptamento e o fortalecimento de StatementHandler e ResultSetHandler em uma mesma classe? Não é? (Será? Você acha que o princípio de responsabilidade única e o princípio de abertura e fechamento são merda?), então, qual é a necessidade de forçar o uso do mesmo interface?
Além disso, use a anotação @Signature para identificar o componente método que deve ser interceptado, se a anotação estiver errada, a compilação também não emitirá erro, e só será descoberto no tempo de execução, veja o exemplo acima:
Supondo que eu esteja focando em3.3.0 versão implementou um plugin:
@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) { } }
Depois, atualize para3.4.0, e o resultado é que o compilação continua normal, mas ao executar, uma exceção é lançada.
4.O cache do Mybatis é praticamente inútil, e independentemente de ter configurado ou não a necessidade de usar o cache, e se atualizar o cache, sempre é necessário calcular o CacheKey. Em situações onde não se usa cache nem atualiza cache, essa computação é completamente desperdiçada.
5.A execução em lote do Mybatis, veja um exemplo JDBC a seguir:
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(NOME_CAMPO}}1, NOME_CAMPO2, NOME_CAMPO2)VALUES(?,?,? ps = conn.prepareStatement(sql); for(int i = 0; i < 10; i++{ String random = RandomStringUtils.randomAlphabetic(8); ps.setString(1, "TEST");//NOME_CAMPO1 ps.setString(2, "dados" + random);//NOME_CAMPO2 ps.setString(3, "parâmetro" + random);//NOME_CAMPO3 ps.addBatch(); } int[] rs = ps.executeBatch(); }finally{ try{ ps.close(); catch(Exception e){} } }
O código não tem um sentimento de inconformidade, pode ser executado normalmente e pode ser rolando conforme esperado, isso é, a mesma connection no mesmo transaction pode executar sql normal e batch ao mesmo tempo, mas se você tentar mudar a maneira de execução na mesma SqlSession da transaction, a resposta que você recebe é - não pode mudar a maneira de execução na mesma transaction!
6、Compatibilidade de produtos de banco de dados: O Mybatis entrega o controle do SQL aos desenvolvedores, então moralmente ocupa o ponto alto - você não é compatível, é por falta de nível! Mas, isso é a postura correta de um framework realmente excelente? Por que não fornecer algumas implementações complementares de compatibilidade? Por exemplo, o DECODE função, que é venerada como um deus em Oracle, não pode fornecer um <decode> tag no SqlMapper, e silenciosamente mudar para CASE WHEN? Ou, não há problema se o oficial não fornecer, mas você deve fornecer uma maneira de expandir, então voltamos ao: a expansibilidade é muito ruim, a expansibilidade é muito ruim, a expansibilidade é muito ruim. A coisa importante é dizer três vezes, mas, eu disse seis vezes.
O que foi mencionado acima são os problemas de deficiência do Mybatis que o editor apresentou, esperando que ajude a todos!