Postgresql Spring数据JPA中的错误:Spring数据返回列表<;BigInteger>;而不是列表<;长期>;

Postgresql Spring数据JPA中的错误:Spring数据返回列表<;BigInteger>;而不是列表<;长期>;,postgresql,hibernate-mapping,spring-data-jpa,Postgresql,Hibernate Mapping,Spring Data Jpa,我在spring数据上实现了DAO: public interface TestDataRepository extends CrudRepository<DpConfigData, Long> { @Query(value = "select distinct(oid) from unit", nativeQuery = true) List<Long> testMethod(); } 公共接口TestDataRepository扩展了Crudepositor

我在spring数据上实现了DAO:

public interface TestDataRepository extends CrudRepository<DpConfigData, Long> {
@Query(value = "select distinct(oid) from unit", nativeQuery = true)
    List<Long> testMethod();
}
公共接口TestDataRepository扩展了Crudepository{
@查询(value=“从单元中选择不同的(oid)”,nativeQuery=true)
列出testMethod();
}
和单元测试,以测试menioned DAO:

@Test
public void test(){
    List<Long> testData = dpConfigDataEntityDataRepository.testMethod();
    for (Long oid:testData){
        System.out.print(oid);
    }
}
@测试
公开无效测试(){
List testData=dpConfigDataEntityDataRepository.testMethod();
for(长oid:testData){
系统输出打印(oid);
}
}
运行测试会产生奇怪的结果-
列出运行时的测试数据
由biginger实例填充,而不是由Long填充。结果我得到ClassCastException:java.math.biginger不能转换为java.lang.Long

JPA实现-Hibernate。 由于DB我使用PostgreSQL,
unit.oid
字段在DB层上具有BigInt类型。 在获取整个单元的情况下,它被映射为Long,但当自定义查询为“selectdistinct…”时,出现了一些错误,它被映射为biginger

那么,我的问题是:这种奇怪行为的原因是什么?
如何优雅地解决它?

postgresql中的BigInt映射到biginger,因为它是无符号的


我认为您最好的选择是将JPA对象中的oid从Long更改为BigInteger

最后,我通过在“服务”层上手动映射解决了这个问题。 示例(伪代码):

公共接口TestDataRepository扩展了Crudepository{
@查询(value=“从单元中选择不同的(oid)”,nativeQuery=true)
列出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;
    }
}
公共类TestServiceImpl扩展了TestService{
脉冲列表测试方法(){
List rawList=testDataRepository.testMethod();
List resultList=newarraylist(rawList.size());
用于(对象rw:rawList){
add(Long.valueOf(String.valueOf(rw));
}
返回结果列表;
}
}

这是Spring数据JPA的一个问题。 如果在DB中,数据类型被定义为BigInteger,并且在JPA查询中,我们尝试获取尽可能长的数据类型,那么它不会给出任何错误,但它在Long数据类型中将值设置为BigInteger

解决方案:

  • 使用biginger作为返回类型

    @Query(value=“从单元中选择不同的(oid)”,nativeQuery=true)
    列出testMethod()

    然后按如下所示设置变量。
    Long变量=bigIntegerValue.longValue()

  • 使用字符串作为返回类型并转换为Long

    @Query(value=“从单元中选择不同的(oid)”,nativeQuery=true)
    列出testMethod()

    然后将该值设置为

    Long变量=Long.valueOf(stringValue)

  • 将DB列类型更改为整数/数字

  • 实体对象获取值

    Long变量=dpConfigData.getOid()

    其中,
    dpConfigData
    是实体的对象(dpConfigData.class)


  • 您可以使用以下JPQL进行尝试:

    public interface TestDataRepository extends 
    JpaRepository<DpConfigData, Long> {
    @Query(value = "select distinct(u.oid) from unit u")
       List<Long> testMethod();
      }
    
    公共接口TestDataRepository扩展
    JpaRepository{
    @查询(value=“从单位u中选择不同的(u.oid”)
    列出testMethod();
    }
    

    只需确保您的实体对象对于给定属性也应该具有相同的数据类型Long。

    这个问题似乎在版本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>
    
    
    org.springframework.boot
    spring启动程序父级
    2.1.8.1发布
    
    这是否需要是nativeQuery?如果否,则删除
    ,nativeQuery=true
    ,并查看这是否有帮助。@RobertNiestroj代码仅用作示例。实际上,“选择不同…”更为复杂,两个数据集的“使用联接选择”和“并集”很少。因此,我需要在postgresql中使用native query.BigInt映射到BigInteger,因为它是无符号的-您可以更改您的JPA对象吗?@farrellmr但是oid被正确映射到Long,以防得到整个单元。为什么?对于nativequery和JPA映射,它必须是不同的路径。一个有趣的测试是运行“select distinct(oid)from unit where oid=1”,这样它将返回1个条目,并将签名更改为Long testMethod(),看看这是否有效。顺便说一句,我看了一下您是否可以更改查询中的返回类型,或者定义一个resultmapping,但看不出这种方法有多有趣——另一种方法是在自定义存储中进行转换。在第二种方法中,查询仍然会产生一个BigInteger值。因此,采用第一种方法作为解决方案。谢谢,在第二种方法中,错误-java.math.biginger不能转换为java.lang.StringInteger。这种行为是否有文档记录?我认为这是一个bug,或者至少是最令人惊讶的WTF行为。我想买苹果,有人告诉我买了苹果,但突然我手里拿着桔子…@FrankHopkins这种行为在Spring文档中没有记录,现在不知道文档中有什么。当我遇到错误并调试代码时,我发现了这个bug。对于那些想象“Java怎么能允许这个bug?”的人来说,MYSQL数据库中也发现了这个问题。我尝试了这个方法,但没有解决这个问题。它仍然返回BigDecimal示例:List getUrlMappingIdListByUserIdAndRole(@Param(“userId”)字符串userId);
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>