【问题标题】:Spring Data JPA method + REST: Enum to Integer conversionSpring Data JPA 方法 + REST:枚举到整数的转换
【发布时间】:2017-08-05 02:05:42
【问题描述】:

我有一个端点:

/api/offers/search/findByType?type=X

其中X 应该是Integer 值(我的OfferType 实例的序数值),而Spring 将X 视为String 并将其StringToEnumConverterFactoryStringToEnum 转换器一起应用.

public interface OfferRepository extends PagingAndSortingRepository<Offer, Long> {

    List<Offer> findByType(@Param("type") OfferType type);

}

所以我写了一个自定义的Converter&lt;Integer, OfferType&gt;,它只是通过给定的序号获取一个实例:

public class IntegerToOfferTypeConverter implements Converter<Integer, OfferType> {

    @Override
    public OfferType convert(Integer source) {
        return OfferType.class.getEnumConstants()[source];
    }

}

然后我用Configuration正确注册了它:

@EnableWebMvc
@Configuration
@RequiredArgsConstructor
public class GlobalMVCConfiguration extends WebMvcConfigurerAdapter {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addConverter(new IntegerToOfferTypeConverter());
    }

}

我预计对findByType?type=X 的所有请求都将通过我的转换器,但事实并非如此。

有什么方法可以说所有定义为请求参数的枚举都必须作为Integer 提供?此外,有什么方法可以在全球范围内说它,而不仅仅是针对特定的枚举?

编辑:我在我的类路径中找到了IntegerToEnumConverterFactory,它可以满足我的所有需求。它注册到DefaultConversionService,这是一个默认的转换服务。如何应用?

EDIT2:这是一件微不足道的事情,我想知道是否有一个属性可以打开枚举转换。

EDIT3:在从TypeDescriptor.forObject(value) 得到String 之后,我尝试写一个Converter&lt;String, OfferType&gt;,但没有帮助。

EDIT4: 我的问题是我已将自定义转换器注册放入 MVC 配置(WebMvcConfigurerAdapteraddFormatters)而不是 REST 存储库之一(RepositoryRestConfigurerAdapterconfigureConversionService) .

【问题讨论】:

  • 这个问题与 Spring Data 或 JPA 有什么关系?
  • 因为他使用的是 Spring Data JPA?安德鲁,您要查询的实体是否在适当的字段上有 @Enumerated 注释?如此处所述:stackoverflow.com/questions/17242408/…
  • @PaulNUK,不,它没有
  • @StefanK。他通过 Spring Data REST 使用存储库到 REST 端点的自动映射。它创建自己的控制器。 OP 可能应该在问题中指定这一点,但它有正确的标签。

标签: java spring spring-boot spring-data-jpa spring-data-rest


【解决方案1】:

Spring 将查询参数解析为字符串。我相信它总是使用Converter&lt;String, ?&gt; 转换器将查询参数转换为存储库方法参数。它使用增强的转换器服务,因为它注册了its own converters,例如Converter&lt;Entity, Resource&gt;

因此你必须创建一个Converter&lt;String, OfferType&gt;,例如:

@Component
public class StringToOfferTypeConverter implements Converter<String, OfferType> {

    @Override
    public OfferType convert(String source) {
        return OfferType.class.getEnumConstants()[Integer.valueOf(source)];
    }
}

然后在扩展 RepositoryRestConfigurerAdapter 的类中配置此转换器以供 Spring Data REST 使用:

@Configuration
public class ConverterConfiguration extends RepositoryRestConfigurerAdapter {

    @Autowired
    StringToOfferTypeConverter converter;

    @Override
    public void configureConversionService(ConfigurableConversionService conversionService) {
        conversionService.addConverter(converter);
        super.configureConversionService(conversionService);
    }
}

我尝试将其添加到the basic tutorial,向 Person 类添加了一个简单的枚举:

public enum OfferType {
    ONE, TWO;
}


@Entity
public class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private OfferType type;


    public OfferType getType() {
        return type;
    }

    public void setType(OfferType type) {
        this.type = type;
    }
}

当我打电话时:

http://localhost:8080/people/search/findByType?type=1

我得到的结果没有错误:

{
  "_embedded" : {
    "people" : [ ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/people/search/findByType?type=1"
    }
  }
}

要实现全局枚举转换器,您必须创建一个工厂并使用方法将其注册到配置中:conversionService.addConverterFactory()。下面的代码是修改后的example from the documentation

public class StringToEnumFactory implements ConverterFactory<String, Enum> {

    public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
        return new StringToEnum(targetType);
    }

    private final class StringToEnum<T extends Enum> implements Converter<String, T> {

        private Class<T> enumType;

        public StringToEnum(Class<T> enumType) {
            this.enumType = enumType;
        }

        public T convert(String source) {
            Integer index = Integer.valueOf(source);
            return enumType.getEnumConstants()[index];
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-29
    • 1970-01-01
    • 2016-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-03
    相关资源
    最近更新 更多