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

Análise profunda e análise das deficiências e problemas do Mybatis

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!

Você também pode gostar