【问题标题】:Getting NumberFormatException using Spring Data JPA使用 Spring Data JPA 获取 NumberFormatException
【发布时间】:2019-11-18 09:31:15
【问题描述】:

我正在使用“Spring in action 5”学习 Spring,但遇到了一些问题:当我在第 3 章从 JDBC 切换到 Spring Data JPA(100% 正常工作)时,代码在我尝试打开时停止工作带有 taco 成分的主页。我做了一些日志来查看发生了什么,发现方法 findById(String id) 无法从 DB(或类似的东西)转换我的值。我正在使用 MySQL。

我尝试使用@Autowired自己调用convertor的方法convert(String id),但我发现的唯一一件事是,当key错误时,会出现另一个错误。所以数据是可见的。我将尝试在这里提供一些代码,但我不确定哪些有用,哪些没有。我在第一次尝试记录某些内容时遇到错误。 IDE 和浏览器中的错误是不同的。 这是完整的项目https://github.com/thedistantblue/taco-cloud-jpa

这是我的转换器:

    public class IngredientByIdConverter implements Converter<String, 
    Ingredient> {

    private IngredientRepository ingredientRepo;

    @Autowired
    public IngredientByIdConverter(IngredientRepository ingredientRepo) {
        this.ingredientRepo = ingredientRepo;

    }
    @Override
        public Ingredient convert(String id) {
            log.info("In converter.convert(): " 
        +ingredientRepo.findById(id).toString());
            Optional<Ingredient> optionalIngredient = 
        ingredientRepo.findById(id);
            return optionalIngredient.orElse(null);
        }
    }

和控制器类:

    @Slf4j
    @Controller
    @RequestMapping("/design")
    @SessionAttributes("order")
    public class DesignTacoController {

    @ModelAttribute(name = "order")
    public Order order() {
        return new Order();
    }

    @ModelAttribute(name = "taco")
    public Taco taco() {
        return new Taco();
    }

    private final IngredientRepository ingredientRepository;
    private TacoRepository designRepository;
    private IngredientByIdConverter converter;

    @Autowired
    public DesignTacoController(IngredientRepository ingredientRepository,
                                TacoRepository designRepository,
                                IngredientByIdConverter converter) {
        this.ingredientRepository = ingredientRepository;
        this.designRepository = designRepository;
        this.converter = converter;
    }

    @GetMapping
    public String showDesignForm(Model model) {
        List<Ingredient> ingredients = new ArrayList<>();



        log.info(converter.convert("CARN").getName());
        log.info("in DTC: " + ingredientRepository.findAll());

        ingredientRepository.findAll().forEach(i -> ingredients.add(i));

在 IDE 中:

java.lang.NumberFormatException:对于输入字符串:“PROTEIN” 在 java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054) ~[na:na] 在 java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110) ~[na:na] 在 java.base/java.lang.Double.parseDouble(Double.java:543) ~[na:na]

在浏览器中:

出现意外错误(类型=内部服务器错误,状态=500)。 对于输入字符串:“PROTEIN”;嵌套异常是 java.lang.NumberFormatException:对于输入字符串:“PROTEIN” org.springframework.dao.InvalidDataAccessApiUsageException:对于输入字符串:“PROTEIN”;嵌套异常是 java.lang.NumberFormatException:对于输入字符串:“PROTEIN” 在 org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:373) 在 org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255) 在 org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527) 在 org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61) 在 org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242) 在 org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)

【问题讨论】:

  • 根据您的实体定义,可能缺少@Enumerated 注释:stackoverflow.com/a/21073312/2958086
  • @Compass,非常感谢!现在工作得很好。但我可以问一下这个例外的性质以及幕后发生的事情吗?
  • 通常,您通过映射值存储 ENUM 以节省 DB 上的空间,即 0、1、2、3、4。这允许您在不破坏数据库的情况下修改实际的 ENUM 显示值。如果只是为了练习,可以使用String值,但是如果PROTEIN突然变成前端的PROTEINS,就得在后端映射PROTEIN -> PROTEINS,比较麻烦。 @Enumerated 基本上采用字符串值的面值。

标签: java spring jpa numberformatexception


【解决方案1】:

对于 Ingredient.java 需要为字段Type type添加注解@Enumerated(EnumType.STRING)

@Id
@NaturalId(mutable = false)
private final String id;
private final String name;
@Enumerated(EnumType.STRING)
private final Type type;

public static enum Type {
    WRAP, PROTEIN, VEGGIES, CHEESE, SAUCE
}

【讨论】:

    【解决方案2】:

    @Pavel 的解决方案确实有效。

    我只是想指出还有一件事,可能值得检查。

    这本书在 JPA 之前讨论了 JDBC,它使用 data.sql 将数据插入到表 'Ingredient' 中。在data.sql文件中,'Ingredient.Type'的类型为String,其值包含'WRAP'、'PROTEIN'等。

    但是,在 JPA 的示例中,data.sql 的内容被移动到 TacoCloudApplication,写入方法 'dataLoader' 中,并且在该方法中,您可以看到它只是创建了带有 Ingredient.Type 的成分实例(不是字符串)。

    要找出两种方法之间的区别,您可以运行 TacoCloudApplication,然后查找表 'Ingredient'。

    如果使用 JDBC 版本示例代码,Type 字段的值为 String。如果使用 JPA 版本示例代码,Type 字段的值为整数。

    【讨论】:

      猜你喜欢
      • 2013-03-07
      • 2020-03-11
      • 2020-04-22
      • 1970-01-01
      • 2013-03-22
      • 2019-07-26
      • 2016-02-08
      • 1970-01-01
      • 2018-11-06
      相关资源
      最近更新 更多