MyBatis大小写不敏感的反序列化

时间:2019-03-13 09:48:37

标签: java jackson mybatis ibatis jackson-databind

从数据库反序列化枚举时,我希望具有一些鲁棒性。基本上,数据库"alpha", "Alpha", "ALPHA"中的条目应全部反序列化为ALPHA枚举。 MyBatis 3.4.6如何做到?

Java枚举类:

import com.fasterxml.jackson.annotation.JsonProperty;

public enum Greek {
    @JsonProperty("Alpha") ALPHA,
    @JsonProperty("Beta") BETA
}

MyBatis映射器和服务

import org.apache.ibatis.annotations.Mapper;
import java.util.List;

@Mapper
public interface EZRatingMapper {
    List<Greek> getGreeks();
}

public class GreekService {
    private final GreekMapper greekMapper;

    @Inject
    public GreekService(GreekMapper dbMapper){
        this.greekMapper = dbMapper;
    }

    @Transactional
    public List<Greek> getGreeks() {
        return greekMapper.getGreeks();
    }
}

MyBatis xml:

<select id="getGreeks" resultType="Greek">
    SELECT greek FROM `greek_table`
</select>

对于Jsons的反序列化,我使用Jackson 2.9.1达到了所需的鲁棒性:

import com.fasterxml.jackson.databind.ObjectMapper;

ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true);
Greek greek = mapper.readValue(jsonString, Greek.class);

1 个答案:

答案 0 :(得分:1)

修改SQL查询的最简单选项。 在查询中将枚举值转换为大写:

<select id="getGreeks" resultType="Greek">
    SELECT UPPER(greek) greek FROM `greek_table`
</select>

在这种情况下不能直接使用但在其他情况下可以使用的另一个选项是使用自定义类型处理程序。

在当前的mybatis版本(3.5.0)中,无法为返回的主要实体指定类型处理程序,因此对于返回枚举值的查询,不能使用自定义类型处理程序。但是在很多情况下,当枚举数是映射器返回的对象的字段时,它就起作用了。

您可以创建自己的类型处理程序,例如:

public class GreekEnumTypeHandler extends BaseTypeHandler<Greek> {

  @Override
  public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
    if (jdbcType == null) {
      ps.setString(i, parameter.name());
    } else {
      ps.setObject(i, parameter.name(), jdbcType.TYPE_CODE);
    }
  }

  @Override
  public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
    String s = rs.getString(columnName);
    return s == null ? null : Greek.valueOf(s.toUpperCase());
  }

  @Override
  public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    String s = rs.getString(columnIndex);
    return s == null ? null : Greek.valueOf(s.toUpperCase());
  }

  @Override
  public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    String s = cs.getString(columnIndex);
    return s == null ? null : Greek.valueOf(s.toUpperCase());
  }
}

然后像这样在映射器中使用它:

<resultMap id="entityMap" type="Entity">
  <id property="id" column="id"/>
  <result property="greek" column="greek" typeHandler="GreekEnumTypeHandler"/>
</resultMap>

<select id="getEntity" resultMap="entityMap">
    SELECT id, greek FROM entity
</select>