2014-10-30 3 views
1

검색 case 문에 대한 데이터 유형을 판별 할 수 없습니다 :QueryDSL 내가 나에게 예외를 제공하는 QueryDSL 문이

Caused by: org.hibernate.QueryException: Could not determine data type for searched case statement [select distinct rollout, count(bTS), sum(case when bTS.status = ?1 then ?2 else ?3 end), sum(case when (bTS.status = ?4) then ?2 else ?3 end), ((sum(case when (bTS.status = ?4) then ?2 else ?3 end)/?5) * count(bTS)) as percentage 
from com.nsn.nitro.project.data.jpa.domain.RolloutAdmin rolloutAdmin, com.nsn.nitro.project.data.jpa.domain.BTS bTS 
    inner join rolloutAdmin.rollout as rollout 
    inner join rolloutAdmin.admin as admin 
where bTS.rollout.id = rollout.id and admin = ?6 
group by rollout 
order by percentage asc] 

나는 여기

쿼리입니다 ... 무슨 일이 case 문을 검색하는 궁금해 :

query.from(qRolloutAdmin, qBTS); 
query.innerJoin(qRolloutAdmin.rollout, qRollout); 
query.innerJoin(qRolloutAdmin.admin, qAdmin); 
BooleanBuilder builder = new BooleanBuilder(); 
builder.and(qBTS.rollout.id.eq(qRollout.id)); 
builder.and(qAdmin.eq(admin)); 
query.where(builder); 
NumberExpression<Integer> statusPlanned = qBTS.status.when(com.nsn.nitro.project.data.utils.BTSStatus.PLANNED).then(new Integer(1)).otherwise(new Integer(0)); 
NumberExpression<Integer> statusCompleted = new CaseBuilder().when(qBTS.status.eq(com.nsn.nitro.project.data.utils.BTSStatus.COMPLETED)).then(new Integer(1)).otherwise(new Integer(0)); 
NumberExpression<Integer> btsNbPlanned = statusPlanned.sum(); 
NumberExpression<Integer> btsNbCompleted = statusCompleted.sum(); 
NumberExpression<Integer> btsPercentage = statusCompleted.sum().divide(new Integer(100)).multiply(qBTS.count()); 
ComparablePath<Integer> percentage = Expressions.comparablePath(Integer.class, "percentage"); 
NumberExpression<Integer> percentage = btsPercentage.as("percentage").as(percentage); 
query.groupBy(qRollout); 
query.orderBy(percentage.asc()); 
QRolloutMeta qRolloutMeta = new QRolloutMeta(qRollout, qBTS.count(), btsNbPlanned, btsNbCompleted, btsPercentage); 
List<RolloutMeta> resultList = query.distinct().list(qRolloutMeta); 

편집 :

: 닉의 솔루션 다음 작업 문

내 기본 쿼리를 필요가 없습니다 더 이상 :

@Override 
@Transactional 
public Page<RolloutMeta> findMetaByAdmin(Admin admin, Pageable page) { 
    Query query = rolloutRepository.getEntityManager().createNativeQuery("SELECT r.id, r.country_id, r.operator_id, r.name, r.description, r.creation_datetime, r.start_datetime, r.end_datetime, count(b.id) as btsNbAll, ifnull(sum(b.status = :statusPlanned), 0) as btsNbPlanned, ifnull(sum(b.status = :statusCompleted), 0) as btsNbCompleted, ifnull(sum(b.status = :statusCompleted), 0) * 100.0/count(b.id) as btsPercentage FROM rollout r, rollout_admin ra, bts b WHERE b.rollout_id = r.id AND r.id = ra.rollout_id AND ra.admin_id = :adminId GROUP BY r.id ORDER BY btsPercentage ASC"); 
    query.setParameter("statusPlanned", BTSStatus.PLANNED.getStatus()); 
    query.setParameter("statusCompleted", BTSStatus.COMPLETED.getStatus()); 
    query.setParameter("adminId", admin.getId()); 
    List<RolloutMeta> resultList = new ArrayList<RolloutMeta>(); 
    List<Object[]> objectList = query.getResultList(); 
    long total = objectList.size(); 
    query.setMaxResults(page.getPageSize()); 
    query.setFirstResult(page.getOffset()); 
    objectList = query.getResultList(); 
    for (Object[] object : objectList) { 
     Rollout rollout = new Rollout(); 
     rollout.setId(((BigInteger) object[0]).longValue()); 
     Long countryId = ((BigInteger) object[1]).longValue(); 
     Country country = countryRepository.findOne(countryId); 
     if (country != null) { 
      rollout.setCountry(country); 
     } 
     Long operatorId = ((BigInteger) object[2]).longValue(); 
     Operator operator = operatorRepository.findOne(operatorId); 
     if (operator != null) { 
      rollout.setOperator(operator); 
     } 
     rollout.setName((String) object[3]); 
     rollout.setDescription((String) object[4]); 
     rollout.setCreationDatetime(new DateTime((Timestamp) object[5])); 
     rollout.setStartDatetime(new DateTime((Timestamp) object[6])); 
     rollout.setEndDatetime(new DateTime((Timestamp) object[7])); 
     Long btsNbAll = ((BigInteger) object[8]).longValue(); 
     Integer btsNbPlanned = ((BigDecimal) object[9]).intValue(); 
     Integer btsNbCompleted = ((BigDecimal) object[10]).intValue(); 
     Integer btsPercentage = ((BigDecimal) object[11]).intValue(); 
     resultList.add(new RolloutMeta(rollout, btsNbAll, btsNbPlanned, btsNbCompleted, btsPercentage)); 
    } 
    return new PageImpl<RolloutMeta>(resultList, page, total); 
} 

답변

3

난 당신이 지금이 문제를 해결 근무했습니다,하지만 난 그냥 같은 문제를 가로 질러 온 것 같아요. 그것은 https://hibernate.atlassian.net/browse/HHH-9343과 관련이있는 것 같습니다. Hibernate는 .when (...).. (...) 리터럴 매개 변수로 재미있는 일을 한 다음 데이터 유형을 결정할 수 없습니다.

어쨌든 Integer 리터럴을 Number Expressions로 변경하여 해결했습니다.

NumberExpression<Integer> statusPlanned = qBTS.status.when(com.nsn.nitro.project.data.utils.BTSStatus.PLANNED).then(NumberTemplate.ONE).otherwise(NumberTemplate.ZERO); 
+0

오 마이 ... 나는 이것이 고칠 수 없다고 생각합니다. 굉장한 직업 닉! NumberTemplate.ZERO NumberTemplate.ONE 및 NumberTemplate.create (Integer.class, "100") 리터럴 매개 변수를 바꾼 다음 작동했습니다. – Stephane