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

Глубокий анализ недостатков и проблем Mybatis

Mybatis является очень популярной платформой для работы с базами данных в отрасли, легковесной и удобной в использовании, в области финансового IT она занимает лидирующую позицию, более популярна, чем Hibernate, и имеет множество преимуществ, которые также очень值得我们学习. Но Mybatis не идеален, его собственный дизайн и кодирование также имеют много недостатков, даже дефектов. Эта статья кратко обсуждает эти недостатки:

Mybatis использует DTD в качестве файла проверки XML-конфигурации, но显然, DTD уже почти устарела, функциональность очень ограничена, расширяемость очень низка, расширяемость очень низка, расширяемость очень низка, и читаемость также не очень хороша. Spring может с достоинством перейти от DTD к XSD, но Mybatis до сих пор не имеет такой смелости.

2. Некорректно выполнена версия совместимости. Возьмем, к примеру, обновление с 3.3.0 до 3.4.0. По общепринятым стандартам отрасли, при обновлении второго уровня версии можно добавлять функции, но необходимо обеспечить обратную совместимость. Однако做法 Mybatis не完全是 таким, посмотрите на ключевой метод prepare ключевого интерфейса StatementHandler:

// 3.3.0
Statement prepare(Connection connection)
throws SQLException;
// 3.4.0
Statement 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){}
{}
{}

Код не вызывает чувства дискомфорта, его можно выполнить нормально, и он может быть возвращен по ожидаемому сценарию, то есть в одной транзакции можно одновременно запускать обычные sql и batch, но если вы попробуете это в одной транзакции SqlSession, вам будет предложено — не lehet переключаться на разные способы выполнения в одной транзакции!

6. Совместимость с базами данных: Mybatis передает контроль над SQL разработчику, что с моральной точки зрения占据制高点——вы не совместимы, это ваша личная квалификация! Но это ли правильное поведение для действительно优秀ного фреймворка? Почему не предоставить一些 вспомогательные меры по обеспечению совместимости? Например, DECODE функция, почитаемая как божественная в Oracle, не могла бы предложить тег <decode> в SqlMapper, чтобы в будущем он默默 изменялся на CASE WHEN? Или, если официальные лица не предоставляют этого, вы должны предоставить способ расширения, и我们又 возвращаемся: очень плохая расширяемость, очень плохая расширяемость, очень плохая расширяемость. Важно повторить это трижды, но я уже сказал это шесть раз.

Ниже приведены недостатки и проблемы Mybatis,介绍的给大家,希望对大家有所帮助!

Вам может понравиться