MyBatis learning notes -- implementation and automatic registration of MyBatis universal type processor

Overview and background

In actual projects, we often have to deal with some enumerated data. For example, the status of an order can be divided into many statuses, such as ordered, paid, shipped, order completed, etc. generally, we only store a number in the database to represent various statuses. However, if the foreground is displayed, the name needs to be displayed to the user, so a transformation is involved. We've seen too many dead judgments written on the front end through if and else. In this way, there is nothing in the initial stage, and it is difficult to expand and maintain in the later stage. In view of this situation, let's consider whether we can directly return the enumeration to the front end, so that the front end takes value when displaying and passes key when saving? In this way, the front end does not need to write a pile of judgments.

Project structure


The structure of the project is shown in the figure above. It mainly has seven parts, of which 1, 4 and 7 are necessary to operate the database through MyBatis. We only do brief analysis, and the rest, such as general type processing, GeneralEnumHandler and overriding TypeHandlerRegistry class, will be the objects we focus on.

Enumeration class base class

public interface BaseEnum<E extends Enum<?>, T> {
    /**
     * The value that is actually mapped to the database
     * @return
     */
    T getKey();

    /**
     * Information displayed
     * @return
     */
    String getValue();
}

As a universal template, the enumeration class base class mainly defines the methods to obtain key and value for subclass implementation. Then its incoming generic < e extends enum <? >, T> One is the enumeration class itself, and the other is the type of the enumerated key.

Design of general type processor

// All custom type processors need to implement TypeHandler or inherit BaseTypeHandler class.
public class GeneralEnumHandler<E extends BaseEnum> extends BaseTypeHandler<E> {
    private Class<E> type;
    private E[] enums;
	   //Parameter set to preparedStatement
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, E e, JdbcType jdbcType) throws SQLException {
        if (jdbcType == null) {
            preparedStatement.setObject(i, e.getKey());
        } else {
            preparedStatement.setObject(i, e.getKey(), jdbcType.TYPE_CODE);
        }
    }
   //Set parameters to preparedStatement
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, E e, JdbcType jdbcType) throws SQLException {
        if (jdbcType == null) {
            preparedStatement.setObject(i, e.getKey());
        } else {
            preparedStatement.setObject(i, e.getKey(), jdbcType.TYPE_CODE);
        }
    }

    //Find the corresponding result of its enum and return
    @Override
    public E getNullableResult(ResultSet resultSet, String s) throws SQLException {
        if (resultSet.wasNull()) {
            return null;
        }
        Object key = resultSet.getObject(s);
        return locateEnumsStatus(key);
    }
   // Omit some methods.
    /**
     * @param key
     * @return
     */
    private E locateEnumsStatus(Object key) {
        if (key instanceof Integer) {
            for (E anEnum : enums) {
                if (anEnum.getKey() == key) {
                    return anEnum;
                }
            }
            throw new IllegalArgumentException("Unknown enumeration type:" + key + ",Please check" + type.getSimpleName());
        }
        if (key instanceof String) {
            for (E anEnum : enums) {
                if (anEnum.getKey().equals(key)) {
                    return anEnum;
                }
            }
            throw new IllegalArgumentException("Unknown enumeration type:" + key + ",Please check" + type.getSimpleName());
        }
        throw new IllegalArgumentException("Unknown enumeration type:" + key + ",Please check" + type.getSimpleName());
    }

}

After the above processing, we can configure and use the general processor in the configuration file or mapping file.
We only need to configure in the configuration file (1-1 configuration)


. . . . . . . . . . . . . . . . .
For copyright reasons, please refer to the following for the complete article:

MyBatis learning notes (V) -- implementation and automatic registration of MyBatis general type processor

Tags: Java Framework PostMan

Posted by TheKiller on Sun, 01 May 2022 23:38:36 +0300