spring boot项目报错:Cannot determine value type from string ‘xxxxx’

spring boot项目报错:Cannot determine value type from string 'xxxxxx’

完整报错信如下:

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception 
[Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException:
 Error attempting to get column 'name' from result set.  
 Cause: java.sql.SQLDataException: Cannot determine value type from string '张三'; 
 Cannot determine value type from string '张三'; 
nested exception is java.sql.SQLDataException:
 Cannot determine value type from string '张三'] with root cause

原因分析:
经测试:
当如下情况:实体类创建了一个参数不完整 的构造方法(具有完整参数 的构造方法不会报错!),而没有为此创建一个无参的构造方法时,就会报次错误。

@Data
public class User {
    private int id;
    private String name;
    private int age;
    
    public User( String name, int age) {
        this.name = name;
        this.age = age;
    }
}

解决问题:
再添加一个无参的构造方法,问题解决。代码修改为:

@Data
public class User {
    private int id;
    private String name;
    private int age;

    //Cannot determine value type from string '张三'] with root cause


    public User() {
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

<think>我们遇到了一个类型转换异常:`java.sql.SQLDataException: Cannot determine value type from string '0.00%' when getting column 'percentage'`。这是因为Spring JDBC在尝试将数据库中的字符串`'0.00%'`转换为目标类型(可能是数值类型)时失败。 ### 问题分析 1. **异常原因**:数据库中的`percentage`列存储的是带有百分号(%)的字符串(如`'0.00%'`),而Java实体类中对应的字段可能是`double`、`float`或`BigDecimal`等数值类型。 2. **类型转换机制**:Spring JDBC的`RowMapper`或`ResultSetExtractor`在自动映射时,会尝试将结果集中的列值转换为Java字段的类型。由于字符串中包含非数字字符(%),导致转换失败。 ### 解决方案 #### 方法一:修改数据库字段类型(推荐) 如果可能,将数据库中的`percentage`列改为数值类型(如`DECIMAL(5,2)`),并存储实际的小数值(如0.00,而不是`'0.00%'`)。这样在Java中可以直接映射为数值类型。 #### 方法二:在查询结果中去掉百分号 如果无法修改数据库结构,可以在SQL查询中使用字符串函数去除百分号,然后转换为数值类型: ```sql SELECT CAST(REPLACE(percentage, '%', '') AS DECIMAL(5,2)) AS percentage FROM your_table ``` 这样,查询结果中的`percentage`列就是数值类型,可以直接映射到Java的数值字段。 #### 方法:在Java中自定义类型转换 如果不想修改SQL查询,可以在Java实体类中,将`percentage`字段定义为`String`类型,然后添加一个方法将其转换为数值: ```java public class YourEntity { private String percentage; // 存储原始字符串 public double getPercentageValue() { return Double.parseDouble(percentage.replace("%", "")); } } ``` 或者使用自定义的`RowMapper`: ```java public class YourEntityRowMapper implements RowMapper<YourEntity> { @Override public YourEntity mapRow(ResultSet rs, int rowNum) throws SQLException { YourEntity entity = new YourEntity(); String percentageStr = rs.getString("percentage"); double value = Double.parseDouble(percentageStr.replace("%", "")); entity.setPercentage(value); // 假设实体类中percentage字段是double类型 return entity; } } ``` #### 方法四:使用自定义转换器(如Spring的Converter) 如果使用Spring Data JPA,可以定义一个属性转换器: ```java import javax.persistence.AttributeConverter; import javax.persistence.Converter; @Converter public class PercentageConverter implements AttributeConverter<Double, String> { @Override public String convertToDatabaseColumn(Double attribute) { return attribute == null ? null : String.format("%.2f%%", attribute); } @Override public Double convertToEntityAttribute(String dbData) { return dbData == null ? null : Double.parseDouble(dbData.replace("%", "")); } } ``` 然后在实体类字段上使用: ```java @Convert(converter = PercentageConverter.class) private Double percentage; ``` ### 注意事项 1. **异常处理**:在字符串转换数值时,要处理可能的`NumberFormatException`。 2. **国际化**:不同地区的小数点表示可能不同(如逗号作为小数点),需考虑`Locale`。 3. **性能**:如果数据量很大,在数据库层面转换(方法二)通常比在Java中转换(方法、四)更高效。 ### 总结 根据具体情况选择最佳方案: - 优先考虑修改数据库结构(方法一)或SQL查询(方法二),从源头上解决类型不匹配问题。 - 如果无法控制数据库,则选择在Java中进行转换(方法或方法四)。 §§相关问题§§ 1. 如何在Spring JDBC中自定义类型转换? 2. 数据库设计时如何正确选择字段类型? 3. 如何处理国际化数字格式的转换问题?</think>### 解决 `java.sql.SQLDataException: Cannot determine value type from string '0.00%'` 错误 这个错误发生在 Spring JDBC 尝试将数据库中的字符串 `'0.00%'` 转换为数值类型时。以下是完整的解决方案: --- #### 1. **问题根本原因** - 数据库中的 `percentage` 列存储的是带百分号的字符串(如 `"15.50%"`) - Java 实体类中对应的字段声明为数值类型(如 `double`、`BigDecimal` 等) - Spring JDBC 无法自动将 `"15.50%"` 转换为数值类型 --- #### 2. **最佳解决方案:自定义类型转换器** ```java import org.springframework.jdbc.core.RowMapper; import java.sql.ResultSet; import java.sql.SQLException; public class CustomRowMapper implements RowMapper<YourEntity> { @Override public YourEntity mapRow(ResultSet rs, int rowNum) throws SQLException { YourEntity entity = new YourEntity(); // 手动处理百分比字段 String percentageStr = rs.getString("percentage"); double percentageValue = Double.parseDouble( percentageStr.replace("%", "").trim() ); entity.setPercentage(percentageValue); // 设置其他字段... return entity; } } ``` **使用方式:** ```java @Repository public class YourRepository { @Autowired private JdbcTemplate jdbcTemplate; public List<YourEntity> getData() { String sql = "SELECT * FROM your_table"; return jdbcTemplate.query(sql, new CustomRowMapper()); } } ``` --- #### 3. **备选方案:数据库层处理** 在 SQL 查询中直接转换类型: ```sql SELECT CAST(REPLACE(percentage, '%', '') AS DECIMAL(5,2)) AS percentage, ...其他字段... FROM your_table ``` **Spring JDBC 配置:** ```java @Bean public RowMapper<YourEntity> rowMapper() { return (rs, rowNum) -> { YourEntity entity = new YourEntity(); entity.setPercentage(rs.getBigDecimal("percentage")); // 直接获取数值 return entity; }; } ``` --- #### 4. **实体类优化方案** ```java public class YourEntity { // 使用String类型接收原始数据 private String percentageRaw; // 添加计算属性 public double getPercentageValue() { return Double.parseDouble( percentageRaw.replace("%", "").trim() ); } } ``` **RowMapper 配置:** ```java entity.setPercentageRaw(rs.getString("percentage")); ``` --- #### 5. **使用 Spring Converter(JPA 方案)** ```java import javax.persistence.Converter; import javax.persistence.AttributeConverter; @Converter public class PercentageConverter implements AttributeConverter<Double, String> { @Override public String convertToDatabaseColumn(Double attribute) { return attribute == null ? null : String.format("%.2f%%", attribute); } @Override public Double convertToEntityAttribute(String dbData) { return dbData == null ? null : Double.parseDouble(dbData.replace("%", "")); } } ``` **实体类应用:** ```java @Entity public class YourEntity { @Convert(converter = PercentageConverter.class) private Double percentage; } ``` --- ### **关键注意事项** 1. **异常处理**:在转换时添加 try-catch 处理 `NumberFormatException` 2. **国际化支持**:不同地区可能使用 `,` 代替 `.` 作为小数点 ```java NumberFormat format = NumberFormat.getInstance(Locale.US); format.parse(percentageStr.replace("%", "")); ``` 3. **空值处理**:检查数据库中的 NULL 值 4. **数据验证**:确保字符串格式符合 `\\d+(\\.\\d+)?%` 模式 > 推荐使用**方案2(数据库层处理)**获得最佳性能,或**方案5(Spring Converter)**获得最简洁的代码结构[^1]。
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值