使用 Spring Data JPA 获取 NumberFormatException
Getting NumberFormatException using Spring Data JPA
我正在使用 "Spring in action 5" 学习 Spring 并遇到了一些问题:当我从 JDBC 切换到 Spring Data JPA 时(100% 正常工作)在第 3 章中,当我尝试打开带有 taco 配料的主页时,代码停止工作。我做了一些日志来查看发生了什么,发现方法 findById(String id) 无法从 DB(或类似的东西)转换我的值。我正在使用 MySQL.
我尝试使用@Autowired 自己调用转换器的方法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);
}
}
和控制器class:
@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)
对于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
}
@Pavel 的解决方案确实有效。
我只想指出还有一件事可能值得检查。
这本书讲的是JPA之前的JDBC,用data.sql插入数据到table'Ingredient'。在文件data.sql中,'Ingredient.Type'的类型,其值包含'WRAP'、'PROTEIN'等,是String.
但是在JPA的例子中,data.sql的内容被移到了TacoCloudApplication中,写在方法'dataLoader'中,在这个方法中,可以看到只是创建了Ingredient.Type(不是字符串)的成分实例。
要找出两种方式之间的区别,您可以运行 TacoCloudApplication,然后查找Table 'Ingredient'。
Type字段的值为String,如果使用JDBC版本示例代码。如果使用JPA版本示例代码,则Type字段的值为Interger。
我正在使用 "Spring in action 5" 学习 Spring 并遇到了一些问题:当我从 JDBC 切换到 Spring Data JPA 时(100% 正常工作)在第 3 章中,当我尝试打开带有 taco 配料的主页时,代码停止工作。我做了一些日志来查看发生了什么,发现方法 findById(String id) 无法从 DB(或类似的东西)转换我的值。我正在使用 MySQL.
我尝试使用@Autowired 自己调用转换器的方法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);
}
}
和控制器class:
@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)
对于Ingredient.java需要为字段Type type
@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
}
@Pavel 的解决方案确实有效。
我只想指出还有一件事可能值得检查。
这本书讲的是JPA之前的JDBC,用data.sql插入数据到table'Ingredient'。在文件data.sql中,'Ingredient.Type'的类型,其值包含'WRAP'、'PROTEIN'等,是String.
但是在JPA的例子中,data.sql的内容被移到了TacoCloudApplication中,写在方法'dataLoader'中,在这个方法中,可以看到只是创建了Ingredient.Type(不是字符串)的成分实例。
要找出两种方式之间的区别,您可以运行 TacoCloudApplication,然后查找Table 'Ingredient'。
Type字段的值为String,如果使用JDBC版本示例代码。如果使用JPA版本示例代码,则Type字段的值为Interger。