English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Mybatis is a very popular persistence framework in the industry, lightweight and easy to use, holding a leading position in the financial IT field, more popular than Hibernate, with many advantages and worth learning a lot. However, Mybatis is not perfect, and its own design and coding also have many shortcomings, even defects. This article briefly discusses these defects:
1Mybatis uses DTD as the validation file for XML configuration files, but it is obvious that DTD is almost obsolete, with very limited functions and poor extensibility. It is also difficult to read. Spring can make a splendid transformation from DTD to XSD, but Mybatis has never had the courage to do so.
2Version compatibility is not well done, let's take3.3Version 0 - >3.4Version 0, according to the general industry standards, the2Version upgrade, you can add features, but you must ensure backward compatibility. However, Mybatis does not do it completely like this. Let's look at the key method prepare of the key interface StatementHandler:
// 3.3Version 0 Statement prepare(Connection connection) throws SQLException; // 3.4Version 0 Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException;
Here, no method is added, but a parameter is added directly to the original method! There are many similar examples, but they will not be listed one by one.
3Version 0 uses a generic Interceptor interface, along with annotations such as @Intercepts and @Signature, to intercept multiple components and their various methods, which appears to be very flexible. However, in my view, the structure is not clear enough. Would you put the interception and enhancement of StatementHandler and ResultSetHandler in the same class during actual development? Would you not (would you)? You think the Single Responsibility Principle and Open/Closed Principle are just dog shit, right? Then, why is there a need to force the use of the same interface?
In addition, use the @Signature annotation to specify the component method that needs to be intercepted. If the annotation is incorrect, the compilation will not report an error, and it can only be discovered at runtime. Take a look at the example above:
Assuming I target3.3Version 0 implemented a 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) { } }
Then, upgrade to3.4.0, and the result is that the compilation is always normal, but when it runs, an exception is thrown.
4.Mybatis's cache is almost useless, and whether or not to use the cache, whether to update the cache, you always need to calculate the CacheKey. In the case of not using the cache or not updating the cache, this calculation is completely a waste.
5.Mybatis's batch execution, see the following JDBC example:
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); } try{ ps.close(); } } } 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, "data" + random);//FIELD_NAME2 ps.setString(3, "parameter" + random);//FIELD_NAME3 ps.addBatch(); } int[] rs = ps.executeBatch(); } try{ ps.close(); } } }
The code has no awkward feeling, can execute normally, and can also roll back as expected, that is, the same connection in the same transaction can run normal sql and batch at the same time, but when you try it in the same transaction's SqlSession, the feedback you get is - cannot switch execution methods in the same transaction!
6Database product compatibility: Mybatis hands over the control of SQL to developers, thus occupying the high ground morally - if you are not compatible, that is your own level is not good enough! But, is this the correct posture of a truly excellent framework? Why can't some auxiliary compatibility implementations be provided? For example, in Oracle, the DECODE function is revered as a god, can a <decode> tag be provided in SqlMapper to silently modify it to CASE WHEN? Or, it doesn't matter if the official doesn't provide it, but you have to provide an extension method, and then it goes back to: extremely poor scalability, extremely poor scalability, extremely poor scalability. I have said it three times, but, I have said six times already.
The following is the problem of defect of Mybatis introduced by the editor, hoping it will be helpful to everyone!