MyBatis (XIV) from entry to: type of processor used with MyBatis

Liuzeng Hui teacher recently read the book "MyBatis from entry to the master," a book, rewarding, so the learning process of their own output in a blog format, if wrong, please correct me, as to help you, honored!

How to use this blog mainly on the type of processor in MyBatis.

1. clear demand

Early in the design, enabled field sys_role table has two possible values, where 0 represents disabled, 1 for enabled, and the entity class we are using Interger type:

/**
 * 有效标志
 */
private Integer enabled;

public Integer getEnabled() {
    return enabled;
}

public void setEnabled(Integer enabled) {
    this.enabled = enabled;
}

If you want to add or update information role, we certainly want to check the value enabled field must be 0 or 1, so the initial part of the code might look like this:

if (sysRole.getEnabled() == 0 || sysRole.getEnabled() == 1) {
     sysRoleMapper.updateById(sysRole);

     sysRole = sysRoleMapper.selectById(2L);
     Assert.assertEquals(0, sysRole.getEnabled());
} else {
     throw new Exception("无效的enabled值");
}

This hard-coded way not only looks unfriendly, and not conducive to post-maintenance, if the maintenance programmer bad temper, will call you, ha ha.

So we demand is refused hard-coded, user-friendly encoding value to check enabled fields is valid.

2. Use an enumerated type processors provided by MyBatis

We usually use enumeration to solve this scenario.

First, a new com.zwwhnly.mybatisaction.type package, and then create an enumeration Enabled in the package:

package com.zwwhnly.mybatisaction.type;

public enum Enabled {
    /**
     * 禁用
     */
    disabled,
    
    /**
     * 启用
     */
    enabled;
}

Wherein, disabled corresponding index is 0, enabled a corresponding index.

Then SysRole class is enabled to modify the original field of type Integer:

/**
 * 有效标志
 */
private Enabled enabled;

public Enabled getEnabled() {
    return enabled;
}

public void setEnabled(Enabled enabled) {
    this.enabled = enabled;
}

At this time, the hard-coded original code can be modified to:

if (sysRole.getEnabled() == Enabled.disabled || sysRole.getEnabled() == Enabled.enabled) {
    sysRoleMapper.updateById(sysRole);

    sysRole = sysRoleMapper.selectById(2L);
    Assert.assertEquals(Enabled.disabled, sysRole.getEnabled());
} else {
    throw new Exception("无效的enabled值");
}

Although the above code is the perfect solution to the problem of hard-coded, but this time raises a new question:

Database does not recognize Enabled enumerated type, when adding, as a query or update, it is necessary to convert the database enumeration value int type, when the query data, the database needs to be of type int value into pieces Enabled For type.

With this issue, we add the following test method SysRoleMapperTest test class:

@Test
public void testUpdateById() {
    SqlSession sqlSession = getSqlSession();

    try {
        SysRoleMapper sysRoleMapper = sqlSession.getMapper(SysRoleMapper.class);

        // 先查询出id=2的角色,然后修改角色的enabled值为disabled
        SysRole sysRole = sysRoleMapper.selectById(2L);
        Assert.assertEquals(Enabled.enabled, sysRole.getEnabled());

        // 修改角色的enabled为disabled
        sysRole.setEnabled(Enabled.disabled);

        if (sysRole.getEnabled() == Enabled.disabled || sysRole.getEnabled() == Enabled.enabled) {
            sysRoleMapper.updateById(sysRole);

            sysRole = sysRoleMapper.selectById(2L);
            Assert.assertEquals(Enabled.disabled, sysRole.getEnabled());
        } else {
            throw new Exception("无效的enabled值");
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        sqlSession.close();
    }
}

Run the test code and found that throws an exception as follows:

Error querying database. Cause: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'enabled' from result set. Cause: java.lang.IllegalArgumentException: No enum constant com.zwwhnly.mybatisaction.type.Enabled.1

This is because when dealing with MyBatis Java types and database types, using TypeHandler (type processors) to convert both of these.

MyBatis provides an implementation TypeHandler interface for Java JDBC database type and the type commonly used type.

MyBatis at startup will load all the corresponding JDBC type of processor, using the default processor in processing org.apache.ibatis.type.EnumTypeHandler enumerated type, the processor will convert enum type character string type the use of face value, for Enabled enumeration, it is "disabled" and "enabled" string.

The type of database enabled field is int, so being given to the role Enabled type in the query information of type int value 1 conversion.

So how to solve this problem?

MyBatis also provides another enumeration processor: org.apache.ibatis.type.EnumOrdinalTypeHandler, the processor uses the enumeration index is processed here can solve the problem of converting error.

With this processor, you need to add the following configuration prior resources / mybatis-config.xml in:

<typeHandlers>
    <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"
                 javaType="com.zwwhnly.mybatisaction.type.Enabled"/>
</typeHandlers>

Run again test code, the test passes, outputting the log follows:

DEBUG [main] - ==> Preparing: SELECT id,role_name,enabled,create_by,create_time FROM sys_role WHERE id = ?

DEBUG [main] - ==> Parameters: 2(Long)

TRACE [main] - <== Columns: id, role_name, enabled, create_by, create_time

TRACE [main] - <== Row: 2, ordinary users, 1, 1, 2019-06-2718: 21: 12.0

DEBUG [main] - <== Total: 1

DEBUG [main] - ==> Preparing: UPDATE sys_role SET role_name = ?,enabled = ?,create_by=?, create_time=? WHERE id=?

DEBUG [main] - ==> Parameters: Ordinary users (String), 0 (Integer), 1 (Long), 2019-06-27 18: 21: 12.0 (Timestamp), 2 (Long)

DEBUG [main] - <== Updates: 1

As can be seen from the log, when querying role information, MyBatis will convert 1 to Enabled.enabled, when updating character information, MyBatis will Enabled.disabled converted to 0.

3. custom type of processor

Assuming that enabled field enumeration value is neither literal nor enumeration index value at this time org.apache.ibatis.type.EnumTypeHandlerand org.apache.ibatis.type.EnumOrdinalTypeHandlercan not meet our needs, we need to implement their own type of processor in this case.

First of all modifications enumerated classes Enabled Code:

package com.zwwhnly.mybatisaction.type;

public enum Enabled {

    /**
     * 启用
     */
    enabled(1),

    /**
     * 禁用
     */
    disabled(0);

    private final int value;

    private Enabled(int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

Then the new processor type EnabledTypeHandler at com.zwwhnly.mybatisaction.type package:

package com.zwwhnly.mybatisaction.type;

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

/**
 * Enabled类型处理器
 */
public class EnabledTypeHandler implements TypeHandler<Enabled> {
    private final Map<Integer, Enabled> enabledMap = new HashMap<Integer, Enabled>();

    public EnabledTypeHandler() {
        for (Enabled enabled : Enabled.values()) {
            enabledMap.put(enabled.getValue(), enabled);
        }
    }

    @Override
    public void setParameter(PreparedStatement preparedStatement, int i, Enabled enabled, JdbcType jdbcType) throws SQLException {
        preparedStatement.setInt(i, enabled.getValue());
    }

    @Override
    public Enabled getResult(ResultSet resultSet, String s) throws SQLException {
        Integer value = resultSet.getInt(s);
        return enabledMap.get(value);
    }

    @Override
    public Enabled getResult(ResultSet resultSet, int i) throws SQLException {
        Integer value = resultSet.getInt(i);
        return enabledMap.get(value);
    }

    @Override
    public Enabled getResult(CallableStatement callableStatement, int i) throws SQLException {
        Integer value = callableStatement.getInt(i);
        return enabledMap.get(value);
    }
}

Custom type TypeHandler processor implements the interface, the interface to rewrite the four methods, enumerated types and traversing Enabled field and no reference constructor enabledMap assigned values.

You want to use a custom type of processor, also be added as follows resources / mybatis-config.xml in:

<typeHandlers>
    <!--其他配置-->
    <typeHandler handler="com.zwwhnly.mybatisaction.type.EnabledTypeHandler"
                 javaType="com.zwwhnly.mybatisaction.type.Enabled"/>
</typeHandlers>

Run test code, and outputs the above output log as the log is not repeated here posted.

4. The reference source and

Source Address: https://github.com/zwwhnly/mybatis-action.git , welcome to download.

Liuzeng Hui "MyBatis from entry to the master."

5. Finally

Play a little advertising, welcomed the focus on micro-channel scan code number public: "Shanghai is a stranger" on a regular basis to share Java technology dry goods, so that we progress together.

Guess you like

Origin www.cnblogs.com/zwwhnly/p/11238131.html