programing

Hibernate HQL에서 Oracle의 regexp_like를 사용하는 방법은 무엇입니까?

goodsources 2023. 9. 8. 21:26
반응형

Hibernate HQL에서 Oracle의 regexp_like를 사용하는 방법은 무엇입니까?

사용중입니다oracle 10g그리고.hibernate 3.3.2. 예전에 sql에서 정규표현식을 사용한 적이 있는데 HQL에서 처음 사용합니다.

Query query = getSession().createQuery("From Company company 
where company.id!=:companyId and 
regexp_like(upper(rtrim(ltrim(company.num))), '^0*514619915$' )");

이것은 내 hql이다, 내가 그것을 실행할 때 없이.regex_like기능이 예상대로 실행됩니다.하지만 나는 그것을 실행할 수 없습니다.regex_like표현.

여기에..

중첩 예외는 org.cate입니다.hql.ast.QuerySyntaxException: 예기치 않은 AST 노드: (1행 근처, 66열......)

도와주세요, 어떻게 사용하면 되나요?regex_like동면 상태의 네이티브 쿼리에서?아니면 그렇게 할 수 있는 다른 대안이 있습니다.

실제로 PL/SQL의 조건문을 제외하고는 REGEXP_LIKE의 결과를 어떤 것과도 비교할 수 없습니다.

최대 절전 모드는 항상 출력을 다음과 비교해야 하므로 returnType이 없는 사용자 지정 함수를 받아들이지 않는 것 같습니다.

REGEXP_LIKE('bananas', 'a', 'i') = 1

Oracle에서는 이 함수의 결과를 무와 비교할 수 없기 때문에 사례 조건을 사용하여 솔루션을 제안했습니다.

public class Oracle10gExtendedDialect extends Oracle10gDialect {

    public Oracle10gExtendedDialect() {
        super();
        registerFunction(
          "regexp_like", new SQLFunctionTemplate(StandardBasicTypes.BOOLEAN,
          "(case when (regexp_like(?1, ?2, ?3)) then 1 else 0 end)")
        );
    }

}

그리고 HQL은 다음과 같이 보여야 합니다.

REGEXP_LIKE('bananas', 'a', 'i') = 1

될 겁니다 :)

Hibernate HQL(그리고 Hibernate가 공급자인 한 JPQL)에서 원하는 유형의 데이터베이스별 기능을 가장 확실하게 사용할 수 있습니다.하이버네이트에게 그 기능들에 대해 알려주면 됩니다.3.3에서 유일한 옵션은 사용자 지정 방언을 제공하고 방언의 생성자로부터 함수를 등록하는 것입니다.기본 사투리 수업을 보시면 기능 등록 예시가 많이 나옵니다.일반적으로 현재 사용하는 정확한 방언을 확장하고 단순히 확장 기능을 제공하는 것이 가장 좋습니다(여기에 기능 등록).

흥미로운 점은 오라클이 regexp_like를 함수로 분류하지 않는다는 것입니다.그들은 그것을 조건/약물로 분류합니다.대부분의 이유는 Oracle SQL이 Boolean 데이터 형식을 정의하지 않기 때문이라고 생각합니다. 비록 PL/SQL에서 Boolean을 반환하는 PL/SQL 함수로 정의되고 I would regexp_like가 정의되지만...

현재 Oracle 10gDialect를 사용한다고 가정하면 다음과 같은 작업을 수행할 수 있습니다.

public class MyOracle10gDialect extends Oracle10gDialect {
    public Oracle10gDialect() {
        super();

        registerFunction( 
            "regexp_like", 
             new StandardSQLFunction( "regexp_like", StandardBasicTypes.BOOLEAN )
        );
    }
}

HQL 파서가 부울런을 반환하는 함수를 좋아하는지는 기억할 수 없지만, 그 자체가 술어라는 측면에서 말입니다.대신 true/false를 다른 것으로 변환하고 해당 반환에 대해 확인해야 할 수도 있습니다.

public class MyOracle10gDialect extends Oracle10gDialect {
    public Oracle10gDialect() {
        super();

        registerFunction( 
            "regexp_like", 
             new StandardSQLFunction( "regexp_like", StandardBasicTypes.INTEGER ) {
                 @Override
                 public String render(
                         Type firstArgumentType, 
                         List arguments, 
                         SessionFactoryImplementor factory) {
                     return "some_conversion_from_boolean_to_int(" + 
                             super.render( firstArgumentType, arguments, factory ) +
                             ")";
                 }
             }
        );
    }
}

JPAQL/HQL에서 특정 데이터베이스 기능을 사용할 수 있는 방법을 제공하지 않는 한 특정 데이터베이스 기능에 액세스할 수 없으며 정규식에 대한 기능도 제공하지 않습니다.정규화를 사용하려면 기본 SQL 쿼리를 작성해야 합니다.

또 다른 매우 중요한 점은 몇몇 동료(Oracle DBA)들이 오라클에서 정규화를 절대 사용하지 말라고 했다는 것입니다. 정규화는 인덱싱할 수 없으므로 DB에서 전체 DB 검색을 수행하게 됩니다.테이블에 몇 개의 항목이 있으면 괜찮지만 행이 많으면 성능이 저하될 수 있습니다.

sqlRestriction(최대 절전 모드 버전 4.2.7)과 함께 최대 절전 모드 기준을 사용하는 경우

 Criterion someCriterion = Restrictions.sqlRestriction("regexp_like (column_name, ?, 'i')", "(^|\\s)"+searchValue+"($|\\s|.$)", StringType.INSTANCE);

또는 연산 결과에 따라 숫자 값을 반환하는 유사한 함수를 oracle에 생성하는 방법도 있습니다.그런 거.

CREATE OR REPLACE FUNCTION MY_REGEXP_LIKE(text VARCHAR2, pattern VARCHAR2)
RETURN NUMBER 
IS function_result NUMBER;
BEGIN
  function_result := CASE WHEN REGEXP_LIKE(text, pattern) 
  THEN 1 
  ELSE 0
  END;    
  RETURN(function_result);
END MY_REGEXP_LIKE;

그리고 당신은 사용할 수 있을 것입니다.

MY_REGEXP_LIKE('bananas', 'a') = 1

사양을 사용할 수 있습니다.

 Specification<YourEntity> specification = (root, query, builder) -> builder.equal(builder.selectCase()
            .when(builder.function("regexp_like", Boolean.class, root.get("your_field"), builder.literal("^0*514619915$")), 1)
            .otherwise(0), 1);
    List<YourEntity> yourEntities = yourEntityRepository.findAll(specification);

CriteriaBuilder의 Accessing REGEXP_LIKE 기능이 유용하다고 생각했습니다.Oracle 버전을 기반으로 방언을 추가합니다.

언급URL : https://stackoverflow.com/questions/11793159/how-to-use-oracles-regexp-like-in-hibernate-hql

반응형