Spring-data / Hibernate无法正确处理null值

时间:2015-07-27 14:30:54

标签: hibernate spring-data

传入spring-data方法,null-value param转换为bytea。

简单的测试用例:

我通过电话号码检索用户的DAO方法:

@Query(value = "select * from user_account  \n"
            + "where case when :telNumber is null then telephone is null\n"
            + "           when :telNumber is not null then telephone = :telNumber end", nativeQuery = true)
    List<ProdUser> findUserByTelephoneNumber(@Param("telNumber") String telNumber);

然后单元测试:

    @Test
    public void testUser(){
    ProdUser user = prodUserEntityDataRepository.findUserByTelephoneNumber("345324333").get(0);
    Assert.assertNotNull(user);
    Assert.assertTrue(user.getTelephone().equals("345324333"));

    List<ProdUser> users = prodUserEntityDataRepository.findUserByTelephoneNumber(null); //Exception here
    Assert.assertNotNull(users);
    Assert.assertTrue(users.size() > 0);
    }

在行prodUserEntityDataRepository.findUserByTelephoneNumber(null)我得到例外:

Caused by: org.postgresql.util.PSQLException: ERROR: operator does not exist: character varying = bytea
  Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.

SQL参数日志显示任何空值的类型为bytea,与varchar,nummber,smallint等无法比较。

有没有人知道如何以良好的方式解决这个问题?此问题是否与https://hibernate.atlassian.net/browse/HHH-9165中描述的Hibernate错误有关?

对于DAO,我们使用Spring-Data over Hibernate。作为RDBMS,我们使用PostgreSQL。

PS:对于解决方法,我可以使用类型转换:CAST(:telNumber as varchar),但我不喜欢这个解决方案。我想禁用将null-params转换为 bytea

更新:

我有更简单的例子:

DAO方法:

@Query(value = "select coalesce(:var1, :var2)", nativeQuery = true)
Long coalesce(@Param("var1") Long var1, @Param("var2") Long var2);

单元测试

@Test
    public void coalesce(){
    Assert.assertEquals(prodUserEntityDataRepository.coalesce(1l,2l), Long.valueOf(1l));

    //Here is exeption - org.postgresql.util.PSQLException: ERROR: COALESCE types bytea and bigint cannot be matched
    Assert.assertEquals(prodUserEntityDataRepository.coalesce(null,2l), Long.valueOf(2l));

    Assert.assertNull(prodUserEntityDataRepository.coalesce(null,null));
    }

2 个答案:

答案 0 :(得分:0)

这与Hibernate无关;这就是数据库的工作方式(以及null意味着未知)的关系模型。

您应该在查询中使用is [not] null运算符来检查列(JPQL中的实体属性)是否({1}}。

答案 1 :(得分:0)

尝试一下。

SELECT *
FROM user_account
WHERE telephone IS NOT DISTINCT FROM CAST(CAST(:telNumber AS TEXT) AS BIGINT)

之所以有效,是因为IS DISTINCT FROM接受NULL,而CAST避开了Hibernate / PostgreSQL中的一个错误,该错误中null参数作为BYTEA而不是常规的NULL类型。