IT story

Hibernate : HQL로 NULL 쿼리 매개 변수 값을 설정하는 방법은 무엇입니까?

hot-time 2020. 12. 30. 19:16
반응형

Hibernate : HQL로 NULL 쿼리 매개 변수 값을 설정하는 방법은 무엇입니까?


Hibernate 매개 변수를 "null"로 설정하려면 어떻게해야합니까? 예:

Query query = getSession().createQuery("from CountryDTO c where c.status = :status  and c.type =:type")
.setParameter("status", status, Hibernate.STRING)
.setParameter("type", type, Hibernate.STRING);

제 경우에는 상태 문자열이 null 일 수 있습니다. 나는 이것을 디버깅하고 최대 절전 모드에서 다음과 같은 SQL 문자열 / 쿼리를 생성합니다 .... status = null... 그러나 이것은 올바른 SQL 문이 " status is null" 이어야하므로 MYSQL에서 작동하지 않습니다 (Mysql은 status = null을 이해하지 못하고이를 평가합니다. 내가 읽은 mysql 문서에 따르면 쿼리에 대해 레코드가 반환되지 않도록 false로 설정하십시오.)

내 질문 :

  1. Hibernatenull 문자열을 "is null"로 올바르게 변환하지 않는 이유는 무엇입니까 (그리고 "= null"을 잘못 생성 함)?

  2. 널 안전하도록이 쿼리를 다시 작성하는 가장 좋은 방법은 무엇입니까? nullsafe를 사용하면 "status"문자열이 null 인 경우 "is null"을 만들어야한다는 의미입니까?

대단히 감사합니다!


  1. 최대 절전 모드는 먼저 HQL 쿼리를 SQL로 변환하고 그 후에 만 ​​매개 변수를 바인딩하려고합니다. 즉,에서 param = ?으로 쿼리를 다시 작성할 수 없습니다 param is null.

  2. Criteria API를 사용해보십시오.

    Criteria c = session.createCriteria(CountryDTO.class);
    c.add(Restrictions.eq("type", type));
    c.add(status == null ? Restrictions.isNull("status") : Restrictions.eq("status", status));
    List result = c.list();
    

이것은 Hibernate 특정 문제가 아니며 (단지 SQL 특성 임) 예, SQL과 HQL 모두에 대한 솔루션이 있습니다.

@Peter Lang은 올바른 아이디어를 가지고 있었고 올바른 HQL 쿼리를 가지고있었습니다. 나는 당신이 쿼리 변경 사항을 선택하기 위해 새로운 클린 실행이 필요하다고 생각합니다 ;-)

아래 코드는 절대적으로 작동하며 모든 쿼리를 orm.xml에 보관하면 좋습니다.

from CountryDTO c where ((:status is null and c.status is null) or c.status = :status) and c.type =:type

매개 변수 String이 null이면 쿼리는 행의 상태도 null인지 확인합니다. 그렇지 않으면 등호와 비교합니다.

메모:

문제는 특정 MySql 특성 일 수 있습니다. Oracle에서만 테스트했습니다.

위 쿼리는 c.status가 null 인 테이블 행이 있다고 가정합니다.

매개 변수가 먼저 확인되도록 where 절의 우선 순위가 지정됩니다.

매개 변수 이름 'type'은 SQL에서 예약어 일 수 있지만 쿼리가 실행되기 전에 대체되기 때문에 중요하지 않습니다.

: status where_clause를 모두 건너 뛰어야하는 경우; 다음과 같이 코딩 할 수 있습니다.

from CountryDTO c where (:status is null or c.status = :status) and c.type =:type

다음과 동일합니다.

sql.append(" where ");
if(status != null){
  sql.append(" c.status = :status and ");
}
sql.append(" c.type =:type ");

에 대한 javadoc에서는setParameter(String, Object) 개체 값이 null이 아닌해야한다는 명시 적입니다. 그러나 null이 전달되면 예외가 발생하지 않는 것이 부끄러운 일입니다.

대안은 setParameter(String, Object, Type)있는 않는 내가하지 않도록 무엇을 해요하지만, 널 (null) 값을 허용 Type매개 변수가 가장 적절한 여기에있을 것이다.


is nullHQL에서 사용해야하는 것처럼 보이지만 (널 전위가있는 매개 변수가 둘 이상인 경우 복잡한 순열로 이어질 수 있습니다.) 가능한 해결책은 다음과 같습니다.

String statusTerm = status==null ? "is null" : "= :status";
String typeTerm = type==null ? "is null" : "= :type";

Query query = getSession().createQuery("from CountryDTO c where c.status " + statusTerm + "  and c.type " + typeTerm);

if(status!=null){
    query.setParameter("status", status, Hibernate.STRING)
}


if(type!=null){
    query.setParameter("type", type, Hibernate.STRING)
}

나는 이것을 시도하지 않았지만 :status두 번 사용 하여 확인 하면 어떻게됩니까 NULL?

Query query = getSession().createQuery(
     "from CountryDTO c where ( c.status = :status OR ( c.status IS NULL AND :status IS NULL ) ) and c.type =:type"
)
.setParameter("status", status, Hibernate.STRING)
.setParameter("type", type, Hibernate.STRING);

HQL은 coalesce를 지원 하여 다음과 같은 추악한 해결 방법을 허용합니다.

where coalesce(c.status, 'no-status') = coalesce(:status, 'no-status')

실제 HQL 쿼리의 경우 :

FROM Users WHERE Name IS NULL

당신이 사용할 수있는

Restrictions.eqOrIsNull("status", status)

대신해서

status == null ? Restrictions.isNull("status") : Restrictions.eq("status", status)

다음은 Hibernate 4.1.9에서 찾은 솔루션입니다. 때때로 NULL 값을 가질 수있는 매개 변수를 쿼리에 전달해야했습니다. 그래서 나는 다음을 사용하여 통과했습니다.

setParameter("orderItemId", orderItemId, new LongType())

그 후 쿼리에서 다음 where 절을 사용합니다.

where ((:orderItemId is null) OR (orderItem.id != :orderItemId))

As you can see, I am using the Query.setParameter(String, Object, Type) method, where I couldn't use the Hibernate.LONG that I found in the documentation (probably that was on older versions). For a full set of options of type parameter, check the list of implementation class of org.hibernate.type.Type interface.

Hope this helps!


this seems to work as wel ->

@Override
public List<SomeObject> findAllForThisSpecificThing(String thing) {
    final Query query = entityManager.createQuery(
            "from " + getDomain().getSimpleName() + " t  where t.thing = " + ((thing == null) ? " null" : " :thing"));
    if (thing != null) {
        query.setParameter("thing", thing);
    }
    return query.getResultList();
}

Btw, I'm pretty new at this, so if for any reason this isn't a good idea, let me know. Thanks.

ReferenceURL : https://stackoverflow.com/questions/2123438/hibernate-how-to-set-null-query-parameter-value-with-hql

반응형