MyBatis Дезериализация без учета регистра - PullRequest
0 голосов
/ 13 марта 2019

Я бы хотел иметь некоторую надежность при десериализации Enums из базы данных.По сути, все записи в базе данных "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 mapper и Service

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 Ответ

1 голос
/ 15 марта 2019

Самый простой вариант для изменения SQL-запроса. Преобразуйте значение enum в верхний регистр в запросе:

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

Другой вариант, который нельзя напрямую использовать в этом случае, но можно использовать в других случаях, - это использовать обработчик пользовательского типа.

В текущей версии mybatis (3.5.0) невозможно указать обработчик типа для основной сущности, которая возвращается, поэтому для запроса, в котором возвращаются значения перечисления, обработчик пользовательского типа использовать нельзя. Но во многих случаях, когда enum является полем объекта, возвращаемого картографом, он работает.

Вы можете создать свой собственный обработчик типа что-то вроде:

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>
...