我在spring-data上实现了DAO:
public interface TestDataRepository extends CrudRepository<DpConfigData, Long> {
@Query(value = "select distinct(oid) from unit", nativeQuery = true)
List<Long> testMethod();
}
进行单元测试以测试被管理的DAO:
@Test
public void test(){
List<Long> testData = dpConfigDataEntityDataRepository.testMethod();
for (Long oid:testData){
System.out.print(oid);
}
}
运行测试会产生奇怪的结果 - 运行时的List<Long> testData
由BigInteger实例填充,而不是由Long填充。结果我得到 ClassCastException:java.math.BigInteger无法强制转换为java.lang.Long
JPA实现 - Hibernate。
作为DB我使用PostgreSQL,unit.oid
字段在DB层上有BigInt类型。
在获取整个单元的情况下它被映射到Long,但是使用自定义查询作为“select distinct ...”时出现了错误并且它被映射到BigInteger。
所以,我的问题是:这种奇怪行为的原因是什么? 如何以优雅的方式解决/解决它?
答案 0 :(得分:5)
这是Spring数据JPA的一个问题。 如果在DB中数据类型被定义为BigInteger,并且在JPA查询中我们尝试获取Long,那么它将不会给出任何错误,但它在Long数据类型中将值设置为BigInteger。
<强>解决方案:强>
使用 BigInteger 作为返回类型
@Query(value = "select distinct(oid) from unit", nativeQuery = true)
List<BigInteger> testMethod();
然后将变量设置如下。
Long variable = bigIntegerValue.longValue();
使用字符串作为返回类型并转换为长
@Query(value = "select distinct(oid) from unit", nativeQuery = true)
List<String> testMethod();
然后将值设置为
Long variable = Long.valueOf(stringValue);
将DB列类型更改为整数/数字。
从实体对象中获取值。
Long variable = dpConfigData.getOid();
其中dpConfigData
是实体的对象(DpConfigData.class)
答案 1 :(得分:0)
postgresql中的BigInt映射到BigInteger,因为它是未签名的
我认为您最好的选择是在JPA对象中将oid从Long更改为BigInteger
答案 2 :(得分:0)
最后,我通过手动映射&#34; service&#34;解决了这个问题。层。 示例(伪代码):
public interface TestDataRepository extends CrudRepository<DpConfigData, Long> {
@Query(value = "select distinct(oid) from unit", nativeQuery = true)
List<Object> testMethod();
}
}
然后在服务层我做手动映射:
public class TestServiceImpl extends TestService {
pulic List<Object> testMethod(){
List<Object> rawList = testDataRepository.testMethod();
List<Object> resultList = new ArrayList(rawList.size());
for(Object rw:rawList){
resultList.add(Long.valueOf(String.valueOf(rw)));
}
return resultList;
}
}
答案 3 :(得分:0)
您可以使用JPQL尝试以下操作:
public interface TestDataRepository extends
JpaRepository<DpConfigData, Long> {
@Query(value = "select distinct(u.oid) from unit u")
List<Long> testMethod();
}
只需确保您的实体对象还应具有与给定属性相同的数据类型Long。
答案 4 :(得分:0)
此问题似乎在2.1.8版中已解决
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>