记一次前端调用API接口的bug【请不要使用long,bigint等数据类型给到前端】!!!!!!!!

文章讲述了开发者在调用一个简单的RESTful删除接口时遇到的问题,后端返回ID错误。通过Fiddler发现数字过大导致前端处理时被截断,从而揭示了在处理Number类型数据时应避免使用过大数值的教训。

在一个阳光明媚的早上,在接口对接的过程中,请求了一个删除接口,接口很简单,restfull风格的api,如下

```

delete/{id}

```

请求了一下,明明ID一样后端却说ID传错了,WTF???

明明是后端传来的ID怎么会是错误的?,于是我立马从裤裆里掏出了我的Filddler来看看

果然发现盲点,这鬼ID怎么这么大?

完全不符啊!!在控制台试一下,🆗符合表现,数字被截断了 那么是为什么呢?

查询后MDN发现对于Number类型的定义

结尾

请不要使用离大谱的数字类型,前端处理不了啊!!!!在被浏览器解析的时候就已经出错了,根本不可能处理;

<think>我们遇到了一个类型转换错误:尝试将Cassandra的`DefaultRow`(即查询结果的一行)转换为boolean类型时失败,因为找不到从BIGINT到java.lang.Boolean的编解码器。 根据错误信息,问题发生在`register`方法中,具体是Spring Data Cassandra在将查询结果转换为boolean类型时失败。 分析原因: 1. 可能我们在Repository中定义了一个返回boolean的方法,但实际查询返回的是包含BIGINT类型字段的行(或整个行),而不是一个可以直接转换为boolean的值。 2. 错误信息中提到了BIGINT和Boolean的转换,说明我们的查询可能返回了一个BIGINT类型的列,但是我们的方法期望返回一个boolean。 解决方案步骤: 1. 检查Repository中`register`方法对应的查询方法(可能是通过方法名推导的查询或者自定义的@Query注解)。 2. 确保查询返回的结果可以直接转换为boolean。例如,如果查询返回的是一个数字(0或1),我们可以使用CAST函数将其转换为boolean(在Cassandra中,boolean类型是true/false,与数字不直接兼容,但可以通过条件判断产生boolean结果)。 3. 或者,修改Repository方法的返回类型,使其与查询结果匹配。 具体操作: 假设Repository中有一个方法如下: ```java public interface UserRepository extends CassandraRepository<UserCassandraPO, UUID> { boolean existsByEmail(String email); } ``` 这个方法是通过方法名派生的查询,Spring Data Cassandra会生成一个查询,返回一个计数值(BIGINT),但是方法期望返回boolean。 实际上,Spring Data Cassandra对于`existsBy...`方法会自动处理,将计数结果(大于0)转换为boolean。所以这里可能是一个bug或者配置问题。 但是错误信息提到的是从`DefaultRow`(一行)转换为boolean,而不是从long转换为boolean。这说明查询返回的是一行数据,而不是一个计数值。 因此,另一种可能是我们自定义了@Query,例如: ```java @Query("SELECT * FROM user WHERE email = ?0 LIMIT 1") boolean existsByEmail(String email); ``` 这样查询返回的是整个行,而不是一个简单的值。Spring Data Cassandra不知道如何将整个行转换为boolean。 正确的做法应该是使用计数查询: ```java @Query("SELECT COUNT(*) FROM user WHERE email = ?0") long countByEmail(String email); // 然后通过判断count>0来得到是否存在 // 或者使用existsByEmail方法,让Spring Data自动生成查询 ``` 但是,如果我们想直接返回boolean,可以使用派生查询(不用写@Query): ```java boolean existsByEmail(String email); ``` 或者使用自定义查询并返回一个基本类型(如long)然后转换为boolean(不推荐,因为Spring Data可以自动处理)。 因此,解决方案是: 1. 如果使用了自定义@Query,确保查询返回的是一个可以直接映射为boolean的值(比如一个数字,然后通过Spring转换?但实际上Cassandra的COUNT返回的是BIGINT,而Spring Data Cassandra可以自动将COUNT查询转换为boolean,但是需要正确的方法签名)。 2. 更推荐使用Spring Data Cassandra的派生查询,即直接使用`existsByEmail`而不写@Query。 3. 如果必须使用自定义查询,可以这样写: ```java @Query("SELECT COUNT(*) FROM user WHERE email = ?0") long countByEmail(String email); // 然后在service中 public boolean existsByEmail(String email) { return countByEmail(email) > 0; } ``` 4. 或者,使用Spring Data Cassandra支持的投影接口,但这里不适用。 错误信息中提到的`CodecNotFoundException`可能是因为我们试图将整个行(包含多个字段)转换为一个boolean,而其中某个字段是BIGINT类型,但整个行无法转换为boolean。 因此,检查Repository中`register`方法对应的查询方法(可能是existsByXXX)的定义,确保它没有返回整个行。 如果问题仍然存在,可能需要检查依赖版本,确保Spring Data Cassandra和Cassandra driver的版本兼容。 另外,如果使用了自定义转换器(Converter),也需要检查是否影响。 由于错误信息中提到了`LoggingAspect`,所以可能是切面在处理方法返回时出错,但根源还是Repository方法返回类型和实际查询结果不匹配。 具体代码修正: 错误的方法定义: ```java @Query("SELECT * FROM user WHERE email = ?0") boolean existsByEmail(String email); ``` 修正为: ```java // 使用派生查询(推荐) boolean existsByEmail(String email); ``` 或者自定义查询返回计数: ```java @Query("SELECT COUNT(*) FROM user WHERE email = ?0") long countByEmail(String email); // 然后在业务逻辑中判断>0 ``` 但注意,`existsByEmail`方法名是Spring Data支持的,所以直接使用派生查询即可。 如果问题不是出在exists方法,而是其他方法(如register方法内部调用了某个返回boolean的查询),同样需要检查那个查询。 总结:确保查询返回的结果类型与方法返回类型匹配。 §§相关问题§§ 1. Spring Data Cassandra中如何正确实现existsBy查询? 2. 如何解决Cassandra驱动中的CodecNotFoundException? 3. 自定义@Query注解时,返回类型应该如何选择? 4. 如何调试Spring Data Cassandra的查询结果类型转换问题? 5. 在Cassandra中,如何将COUNT查询结果映射为boolean类型?</think>### 解决 Cassandra 类型转换错误:`CodecNotFoundException` #### 错误原因分析 错误信息表明:**Cassandra 无法将 BIGINT 类型转换为 Java 的 Boolean 类型**。具体发生在 `register` 方法中,当尝试从查询结果 `DefaultRow` 提取值时出现类型不匹配。 #### 核心问题定位 1. **类型映射错误**: - Cassandra 的 `BIGINT` 类型(64位整数)无法直接映射到 Java `Boolean` - 常见于返回数值型数据的查询被误用为布尔判断 2. **典型场景**: ```java // 错误示例:COUNT查询返回long却被当作boolean @Query("SELECT COUNT(*) FROM user WHERE email = ?0") boolean existsByEmail(String email); // 应返回long而非boolean ``` #### 完整解决方案 ##### 1. 修正 Repository 方法签名 ```java public interface UserRepository extends CassandraRepository<UserCassandraPO, UUID> { // 正确:返回计数结果 @Query("SELECT COUNT(*) FROM user WHERE email = ?0") long countByEmail(String email); // 正确:使用派生查询 boolean existsByEmail(String email); // 让Spring自动生成查询 } ``` ##### 2. 业务层转换处理 ```java @Service public class UserService { private final UserRepository repository; public boolean isEmailRegistered(String email) { // 显式转换计数结果为布尔值 return repository.countByEmail(email) > 0; } } ``` ##### 3. 自定义类型转换器(高级方案) ```java @ReadingConverter public class CountToBooleanConverter implements Converter<Long, Boolean> { @Override public Boolean convert(Long count) { return count != null && count > 0; } } // 注册转换器 @Configuration public class CassandraConfig extends AbstractCassandraConfiguration { @Override public CustomConversions customConversions() { return new CassandraCustomConversions(List.of( new CountToBooleanConverter() )); } } // 使用转换器 public interface UserRepository extends CassandraRepository<UserCassandraPO, UUID> { @Query("SELECT COUNT(*) FROM user WHERE email = ?0") @QueryResultMapper(CountToBooleanConverter.class) Boolean existsByEmail(String email); } ``` ##### 4. 验证查询结果类型 ```java // 测试方法 @Test void testEmailExists() { // 1. 执行原始CQL验证返回类型 ResultSet rs = session.execute("SELECT COUNT(*) FROM user WHERE email = 'test@example.com'"); Row row = rs.one(); System.out.println(row.getType(0)); // 应输出 BIGINT // 2. 验证Repository方法 assertThat(repository.countByEmail("test@example.com")) .isInstanceOf(Long.class); } ``` #### 关键排查步骤 1. **检查所有返回布尔值的查询**: ```bash grep -r "boolean.*By" src/main/java/com/yourpackage/repository ``` 2. **验证实体映射关系**: ```java // 添加调试日志 @Bean public CassandraMappingContext cassandraMapping() { CassandraMappingContext context = new CassandraMappingContext(); context.setUserTypeResolver(new SimpleUserTypeResolver(...)); context.setInitialEntitySet(new HashSet<>(List.of(UserCassandraPO.class))); context.afterPropertiesSet(); // 触发映射解析 return context; } ``` 3. **检查驱动类型映射表**: | Cassandra 类型 | Java 类型 | 是否支持布尔转换 | |---------------|---------------|----------------| | BIGINT | Long | ❌ | | BOOLEAN | Boolean | ✅ | | INT | Integer | ❌ | #### 预防措施 ```yaml # application.yml 添加类型检查 spring: data: cassandra: entity-base-packages: com.yourpackage.entity schema-action: VALIDATE # 启动时验证类型映射 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值