【问题标题】:Why EntityManager createNativeQuery lists sometimes return a BigDecimal and other times an Integer?为什么 EntityManager createNativeQuery 列表有时返回 BigDecimal 而有时返回 Integer?
【发布时间】:2012-09-07 21:31:36
【问题描述】:

这让我很困惑很多。我只是弄清楚发生了什么,但我会提出并回答我自己的文档问题,以防它对其他人有所帮助。

我有以下代码:

MyClass.java

    public List<Integer> 
    getPersonIdsByPrograms(Collection<Integer> programIds, boolean getFirst) {
      String sql = "SELECT p.PERSON_ID FROM PERSON p " + 
                   "WHERE p.PROGRAM_ID in (?programIds)";
      sql = sql.replaceAll("\\?programIds", StringUtils.join(programIds, ","));
      Query query = entityManager.createNativeQuery(sql);

      //EntityManager returns scalar values, in this case, BigDecimal
      List<BigDecimal> queryResults = query.getResultList();

      // !! This is the toggle that makes or breaks the tests !!
      // !! !! UPDATE: Red herring. This had no impact.  See answer for why !! !!
      if (getFirst) {
        Object firstObj = queryResults.get(0); //This makes the test pass!?!
        //This is always true
        System.out.println("Is firstObj a BigDecimal? Answer: " 
               + (firstObj instanceof BigDecimal));
      }

      //Returns list of BigDecimal, so need to convert to Integer
      List<Integer> result = Lists.transform(queryResults, new Function<BigDecimal, Integer>() {
        public Integer apply(BigDecimal n) {
            return Integer.valueOf(n.intValue());
        }
    });
    return result;
}

警告 现在这是答案的来源,并且使下面的测试无效,因此请谨慎对待。我认为第一个断言会通过,而第二个断言会失败。情况并非如此:第一次在某些情况下最终失败了。

MyClassTest.java

@Test
public void getPersonIdsByProgramsTest_BigDecimalOrInteger() {
    ArrayList<Integer> programs = Lists.newArrayList(131,141,161,162,0,113,110,26,5,28,50,58,51,29,121,31,101,41,27);
    List<?> personsByPrograms = userDao.getPersonIdsByPrograms(programs, true);
    TestingUtils.assertNotNullOrEmpty(personsByPrograms);
    Object shouldBeInteger = personsByPrograms.get(0);
    assertTrue(shouldBeInteger instanceof Integer);

    personsByPrograms = userDao.getPersonIdsByPrograms(programs, false);
    TestingUtils.assertNotNullOrEmpty(personsByPrograms);
    shouldBeInteger = personsByPrograms.get(0);
    assertTrue(shouldBeInteger instanceof Integer);
}

【问题讨论】:

  • 附带说明,您确定要返回 Lists.transform() 的结果吗,这是一个视图,因此每次访问列表内容时都会重新评估,而不是结果的副本在ArrayListImmutableList?
  • 是的,应该这样做。在这种情况下并非如此,因为我知道在从调用它的方法第一次访问后该列表被丢弃,但为了防止将来使用,它可能会有所帮助。再说一次,这里的转换真的很快。

标签: java database jpa eclipselink guava


【解决方案1】:

答案:不同的数据库可能返回不同的标量类型。

我的问题是使用针对 2 个不同数据库(Oracle 和 MS SQL Server)运行的 @RunWith(Parameterized.class) 单元测试的结果。它可能与列的定义方式有关(我没有研究过),但基本要点是您可能无法依赖 JPA 在数据库之间切换时将转换为的特定对象类型。为了安全起见,您可能只想假设List&lt;? extends Number&gt;

【讨论】:

    猜你喜欢
    • 2019-06-22
    • 2019-12-26
    • 1970-01-01
    • 2017-06-05
    • 2012-03-11
    • 2021-03-23
    • 1970-01-01
    • 1970-01-01
    • 2015-09-15
    相关资源
    最近更新 更多