2015-10-30 13 views
7

Questo codice:Hibernate dà un'eccezione strana ClassCast (usando Transformers)

@Override 
public List<FactCodeDto> getAllFactsWithoutParentsAsFactDto() { 
    String completeQuery = FactCodeQueries.SELECT_DTO_FROM_FACT_WITH_NO_PARENTS; 
    Query query = createHibernateQueryForUnmappedTypeFactDto(completeQuery); 

    List<FactCodeDto> factDtoList = query.list(); //line 133 
    return factDtoList; 
} 

richiamando questo metodo:

private Query createHibernateQueryForUnmappedTypeFactDto(String sqlQuery) throws HibernateException { 
    return FactCodeQueries.addScalars(createSQLQuery(sqlQuery)).setResultTransformer(Transformers.aliasToBean(FactCodeDto.class)); 
} 

mi dà un ClassCastException -> parte del tracciato:

Caused by: java.lang.ClassCastException: be.fgov.just.cjr.dto.FactCodeDto cannot be cast to java.util.Map 
    at org.hibernate.property.access.internal.PropertyAccessMapImpl$SetterImpl.set(PropertyAccessMapImpl.java:102) 
    at org.hibernate.transform.AliasToBeanResultTransformer.transformTuple(AliasToBeanResultTransformer.java:78) 
    at org.hibernate.hql.internal.HolderInstantiator.instantiate(HolderInstantiator.java:75) 
    at org.hibernate.loader.custom.CustomLoader.getResultList(CustomLoader.java:435) 
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2423) 
    at org.hibernate.loader.Loader.list(Loader.java:2418) 
    at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:336) 
    at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1898) 
    at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:318) 
    at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:125) 
    at be.fgov.just.cjr.dao.factcode.FactCodeDAOImpl.getAllFactsWithoutParentsAsFactDto(FactCodeDAOImpl.java:133) 

Il che è piuttosto strano perché, in effetti, se si cerca il codice sorgente di Hibernate si cerca di farlo:

@Override 
@SuppressWarnings("unchecked") 
public void set(Object target, Object value, SessionFactoryImplementor factory) { 
    ((Map) target).put(propertyName, value); //line 102 
} 

Il che non ha alcun senso ...

obiettivo è di tipo Class e questo codice tenta di gettarlo ai Map,

Perché si tenta di farlo ???

tutti i puntatori sono più che benvenuti ...

Sto usando Hibernate 5 (e sto aggiornamento da 3) ...

edit: Io uso anche Primavera (4.2.1.RELEASE; anche l'aggiornamento), che chiama questi metodi su Deploy, tutti i puntatori di debug sono i benvenuti, così ...

Edit 2: (tutta la classe FactCodeDto, come richiesto)

package be.fgov.just.cjr.dto; 

import be.fgov.just.cjr.model.FactCode; 
import be.fgov.just.cjr.model.FactCodeType; 
import be.fgov.just.cjr.utility.FullDateUtil; 
import be.fgov.just.cjr.utility.Locales; 
import lombok.Getter; 
import lombok.Setter; 
import lombok.ToString; 
import org.springframework.util.Assert; 

import java.util.*; 

@Getter 
@Setter 
@ToString 
public class FactCodeDto extends TreeNodeValue { 

    private String cdFact; 
    private String cdFactSuffix; 
    private Boolean isSupplementCode; 
    private Boolean isTitleCode; 
    private Boolean mustBeFollowed; 

    private Date activeFrom; 
    private Date activeTo; 
    private Boolean isCode; 
    private Long idFact; 
    private Long idParent; 
    private String type; 
    Map<Locale, String> description = new HashMap<Locale, String>(3); 

    public FactCodeDto() { 
    } 

    public FactCodeDto(String prefix, String suffix) { 
     super(); 
     this.cdFact = prefix; 
     this.cdFactSuffix = suffix; 
    } 

    public FactCodeDto(String cdFact, String cdFactSuffix, Boolean isSupplementCode, Boolean mustBeFollowed) { 
     super(); 
     this.cdFact = cdFact; 
     this.cdFactSuffix = cdFactSuffix; 
     this.isSupplementCode = isSupplementCode; 
     this.mustBeFollowed = mustBeFollowed; 

    } 

    public FactCodeDto(String cdFact, String cdFactSuffix, Boolean isSupplementCode, Boolean mustBeFollowed, Long idFact, Long idParent, Boolean isCode, Boolean isTitleCode, Date from, Date to, Map<Locale, String> descriptions,String type) { 
     super(); 
     this.cdFact = cdFact; 
     this.cdFactSuffix = cdFactSuffix; 
     this.isSupplementCode = isSupplementCode; 
     this.mustBeFollowed = mustBeFollowed; 
     this.idFact = idFact; 
     this.idParent = idParent; 
     this.isCode = isCode; 
     this.isTitleCode = isTitleCode; 
     this.activeFrom = from; 
     this.activeTo = to; 
     if (descriptions != null) { 
      this.description = descriptions; 
     } 

     this.type = type; 

    } 

    public FactCodeDto(FactCode fc) { 
     this(fc.getPrefix(), fc.getSuffix(), fc.isSupplementCode(), fc.isHasMandatorySupplCodes(), fc.getId(), fc.getParent(), fc.isActualCode(), fc.isTitleCode(), fc.getActiveFrom(), fc.getActiveTo(), fc.getAllDesc(),fc.getType().getCode()); 
    } 

    public String formatCode() { 
     return FactCode.formatCode(cdFact, cdFactSuffix); 
    } 

    public boolean isActive() { 
     Date now = new Date(System.currentTimeMillis()); 
     return FullDateUtil.isBetweenDates(now, this.activeFrom, this.activeTo); 

    } 

    public void setDescFr(String s) { 
     description.put(Locales.FRENCH, s); 
    } 

    public void setDescNl(String s) { 
     description.put(Locales.DUTCH, s); 
    } 

    public void setDescDe(String s) { 
     description.put(Locales.GERMAN, s); 
    } 

    /** 
    * public String toString() { 
    * StringBuilder sb = new StringBuilder(); 
    * sb.append(getIdFact() + ": ") 
    * .append(getIdParent() + ": ") 
    * .append(" " + cdFact + cdFactSuffix + ": " + (isSupplementCode ? "NO Principal " : " Principal ")) 
    * .append((mustBeFollowed ? " Must Be Followed " : "NOT Must Be Followed ")); 
    * return sb.toString(); 
    * } 
    */ 

    public Map<Locale, String> getDescription() { 
     return description; 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     String fullCode = formatCode(); 
     result = prime * result + ((fullCode == null) ? 0 : fullCode.hashCode()); 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) { 
      return true; 
     } 
     if (obj == null) { 
      return false; 
     } 
     if (getClass() != obj.getClass()) { 
      return false; 
     } 
     FactCodeDto other = (FactCodeDto) obj; 

     return formatCode().equals(other.formatCode()); 
    } 

    @Override 
    public boolean isChildOf(TreeNodeValue value) { 
     Assert.notNull(value); 
     boolean isChild = false; 
     if (value instanceof FactCodeDto) { 
      if (this.getIdParent() != null) { 
       isChild = this.getIdParent().equals(((FactCodeDto) value).getIdFact()); 
      } 

     } 
     return isChild; 
    } 

    @Override 
    public boolean isBrotherOf(TreeNodeValue value) { 
     Assert.notNull(value); 
     boolean isBrother = false; 
     if (value instanceof FactCodeDto) { 
      if (this.getIdParent() != null) { 
       isBrother = this.getIdParent().equals(((FactCodeDto) value).getIdParent()); 
      } 

     } 
     return isBrother; 
    } 

    @Override 
    public boolean isParentOf(TreeNodeValue value) { 
     Assert.notNull(value); 
     boolean isParent = false; 
     if (value instanceof FactCodeDto) { 
      isParent = this.getIdFact().equals(((FactCodeDto) value).getIdParent()); 
     } 
     return isParent; 
    } 


    @Override 
    public int compareTo(TreeNodeValue to) { 
     if (to instanceof FactCodeDto) { 
      return formatCode().compareTo(((FactCodeDto) to).formatCode()); 
     } else return 1; 

    } 


    public String getCode() { 
     return formatCode(); 
    } 


} 
+0

vostro obiettivo che hai trovato è di tipo: be.fgov.just.cjr.dto.FactCodeDto che non è una mappa –

+2

sì, lo so, ma voglio per ottenere una lista di tipo FactCodeDto e 'dirlo' in ibernazione tramite setResultTransformer (Transformers.aliasToBean (FactCodeDto.class)) ma poi (per qualche strano motivo) Hibernate tenta internamente di lanciare il mio FactCodeDto.class (target) su una mappa. .. ma non dovrebbe farlo, perché lo fa? – Bamboomy

+0

perché usare tutto questo gonfio quando un semplice criterio o criterio lo risolverebbe? – javaguest

risposta

1

alla fine è w asn't così difficile trovare una soluzione,

Ho appena creato il mio (personalizzato) ResultTransformer e specificato che nel metodo setResultTransformer:

private Query createHibernateQueryForUnmappedTypeFactDto(String sqlQuery) throws HibernateException { 
    return FactCodeQueries.addScalars(createSQLQuery(sqlQuery)).setResultTransformer(new FactCodeDtoResultTransformer()); 
    //return FactCodeQueries.addScalars(createSQLQuery(sqlQuery)).setResultTransformer(Transformers.aliasToBean(FactCodeDto.class)); 
} 

il codice del trasformatore risultato personalizzato:

package be.fgov.just.cjr.dao.factcode; 

import be.fgov.just.cjr.dto.FactCodeDto; 

import java.util.Date; 
import java.util.List; 

/** 
* Created by a162299 on 3-11-2015. 
*/ 
public class FactCodeDtoResultTransformer implements org.hibernate.transform.ResultTransformer { 

    @Override 
    public Object transformTuple(Object[] objects, String[] strings) { 

     FactCodeDto result = new FactCodeDto(); 

     for (int i = 0; i < objects.length; i++) { 
      setField(result, strings[i], objects[i]); 
     } 

     return result; 
    } 

    private void setField(FactCodeDto result, String string, Object object) { 

     if (string.equalsIgnoreCase("cdFact")) { 
      result.setCdFact((String) object); 
     } else if (string.equalsIgnoreCase("cdFactSuffix")) { 
      result.setCdFactSuffix((String) object); 
     } else if (string.equalsIgnoreCase("isSupplementCode")) { 
      result.setIsSupplementCode((Boolean) object); 
     } else if (string.equalsIgnoreCase("isTitleCode")) { 
      result.setIsTitleCode((Boolean) object); 
     } else if (string.equalsIgnoreCase("mustBeFollowed")) { 
      result.setMustBeFollowed((Boolean) object); 
     } else if (string.equalsIgnoreCase("activeFrom")) { 
      result.setActiveFrom((Date) object); 
     } else if (string.equalsIgnoreCase("activeTo")) { 
      result.setActiveTo((Date) object); 
     } else if (string.equalsIgnoreCase("descFr")) { 
      result.setDescFr((String) object); 
     } else if (string.equalsIgnoreCase("descNl")) { 
      result.setDescNl((String) object); 
     } else if (string.equalsIgnoreCase("descDe")) { 
      result.setDescDe((String) object); 
     } else if (string.equalsIgnoreCase("type")) { 
      result.setType((String) object); 
     } else if (string.equalsIgnoreCase("idFact")) { 
      result.setIdFact((Long) object); 
     } else if (string.equalsIgnoreCase("idParent")) { 
      result.setIdParent((Long) object); 
     } else if (string.equalsIgnoreCase("isCode")) { 
      result.setIsCode((Boolean) object); 
     } else { 
      throw new RuntimeException("unknown field"); 
     } 

    } 

    @Override 
    public List transformList(List list) { 
     return list; 
    } 
} 

in modalità ibernazione 3 è possibile impostare Aliasses per le query ma non è più possibile farlo in ibernazione 5 (correggimi se ho torto), quindi l'aliasToBean è qualcosa che puoi usare solo quando usi effettivamente alias; quale non ho, quindi l'eccezione.

+0

È possibile utilizzare alias, vedere la mia risposta http://stackoverflow.com/a/37437567/3405171 –

+0

E è possibile realizzare un trasformatore più semplice e universale, utilizzando la riflessione. –

4

Ho trovato che AliasToBean è cambiato in Hibernate 5. Per me l'aggiunta di getter per il mio campo ha risolto il problema.

+0

per me in condizioni simili Avevo bisogno di cambiare il nome del campo da lasciare dire 'zipcode' a' ZipCode' (aka caso cammello) e rinominare il metodo setter di conseguenza. ma in ogni caso, il testo dell'eccezione potrebbe confondere .. – ashirman

3

Faccio qualche indagine su questa domanda. Il problema è che Hibernate converte gli alias per i nomi delle colonne in maiuscolo - cdFact diventa CDFACT.

Leggi per una spiegazione più profondamente e soluzione qui: mapping Hibernate query results to custom class?

0

mi è stato sempre questa eccezione

ho chiamato uno dei campi in DTO come "closedIndexValue" dopo aver cambiato in "closedindexValue ", il codice funzionava bene. Penso che fosse dovuto al caso della lettera" I ".

closedIndexValue -> CamelCase improprio closedindexValue -> corretta CamelCase

Hibernate Versione: - 5.2.4

0

Questa eccezione si verifica quando le setter e getter e non mappate correttamente ai nomi delle colonne. Assicurarsi di disporre dei getter e setter corretti per la query (nomi corretti e tipi di dati corretti). Per saperne di più su di esso qui:

http://javahonk.com/java-lang-classcastexception-com-wfs-otc-datamodels-imagineexpirymodel-cannot-cast-java-util-map/

+0

Questa risposta non fornisce una soluzione, anche con una mappatura corretta il cast non funzionerebbe. – Bamboomy