如何在spring数据仓库nativeQuery中使用oracle NVL函数

Posted

技术标签:

【中文标题】如何在spring数据仓库nativeQuery中使用oracle NVL函数【英文标题】:How to use oracle NVL function in spring data repository nativeQuery 【发布时间】:2017-11-06 15:56:53 【问题描述】:

我正在尝试在 Spring Data Repository 的 nativeQuery 中使用 oracle 的 NVL 函数。

当我在programId 参数中传递null 值时,它会抛出异常(ORA-00932: inconsistent datatypes: expected NUMBER got BINARY),如果我在“programId”中传递一个有效值,那么它工作正常。

public interface ProgramRulesRepository

  public static final String FIND_PROGRAM_RULES_BY_PARTICIPANT_ID_AND_ROLE_OR_PROGRAM = " SELECT DISTINCT pr.id , pr.program_id , prgm.display_name , pr.group_id , pr.type , pr.cmmo_key FROM  program prgm , program_rule pr , program_audience pa , participant_audience paa WHERE prgm.id = pa.program_id AND pr.program_id = pa.program_id AND pa.audience_id = paa.audience_id AND pr.type = :roleType  AND paa.participant_id = :participantId "
      + " AND pr.program_id = NVL ( :programId ,pr.program_id )";

  @Query( value = FIND_PROGRAM_RULES_BY_PARTICIPANT_ID_AND_ROLE_OR_PROGRAM, nativeQuery = true )
List<Object[]> findByParticipantIdAndRoleTypeOrProgramId( @Param( "participantId" ) Long participantId, @Param( "roleType" ) String roleType, @Param( "programId" ) Long programId );



例外:

Caused by: java.sql.SQLSyntaxErrorException: ORA-00932: inconsistent datatypes: expected NUMBER got BINARY

【问题讨论】:

Spring Data - ignore parameter if it has a null value的可能重复 【参考方案1】:

我在使用 MongoDB 时遇到过这个问题。但是我可以通过使用 mongoTemplate 来解决这个问题,

 Query query = new Query();
 Criteria criteria = new Criteria();
 List<Criteria> orCriterias = new ArrayList<>();
 if( dto.getId() != null)     
   orCriterias.add(Criteria.where("id").is(Integer.parseInt(dto.getId())));
 
 ... so on for other fields
criteria.orOperator(orCriterias.toArray(new Criteria[orCriterias.size()]));
query.addCriteria(criteria);
List<StudentDTO> recordsList = mongoTemplate.find(query, StudentDTO.class, 
"student_collection");

【讨论】:

我通过应用条件忽略空参数并将条件添加到条件列表。然后将“orOperators”、“andOperators”等运算符应用为文档docs.spring.io/spring-data/mongodb/docs/2.0.8.RELEASE/reference/…。然后将该条件列表添加到 Query。 这个东西也在spring jira“jira.spring.io/browse/DATAJPA-209”中讨论。请也参考它以获得想法。【参考方案2】:

在使用 Hibernate 时避免使用 NVL 和 COALESCE。 COALESCE 函数需要具有相同类型的所有参数。 NVL 使用隐式转换,当存在 BINARY 或 VARBINARY 时效果不佳。这个 BINARY 是从哪里来的?好吧,Hibernate 将 NULL 值设置为 BINARY 类型并忽略 Java 支持的真实数据类型。当您将日志记录级别设置为跟踪时,您可以在输出中看到:

binding parameter [1] as [VARBINARY] - [null]

因此,当 COALESCE 或 NVL 函数中的其他类型为例如 NUMBER 时,您将收到错误 ORA-00932。

【讨论】:

【参考方案3】:

这个问题的一个很好的解决方案是:

" AND (:programId IS NULL OR pr.program_id = :programId)"

这样做,如果你的参数为空,这句话将返回TRUE,不会丢弃寄存器,如果不为空,将与存储在其字段中的值进行比较。

【讨论】:

以上是关于如何在spring数据仓库nativeQuery中使用oracle NVL函数的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA nativeQuery 字符串搜索出错

spring-data-jpa 使用 @Query 和 @Modifying 插入而不使用 nativeQuery 或 save() 或 saveAndFlush()

Spring存储库和带有nativeQuery = false的DATA_FORMAT

如何在 Spring Data JPA 中获取 countQuery 返回的计数?

在运行时覆盖 NativeQuery

Spring Data Jpa