2015-10-30 1 views
7

Dieser Code:Hibernate gibt eine seltsame ClassCast Ausnahme (mit 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; 
} 

Aufruf dieser Methode:

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

gibt mir einen Classcast -> Teil der Spur:

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) 

Das ist ziemlich seltsam, denn in der Tat, wenn Sie den Quellcode von Hibernate nachschlagen, versucht es:

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

, die keinen Sinn machen ...

Ziel ist vom Typ Klasse und dieser Code versucht, es Karte zu werfen,

warum es versuchen, das zu tun ???

alle Hinweise sind mehr als willkommen ...

ich Hibernate 5 bin mit (und von 3 Uhr ein Upgrade) ...

edit: ich auch Frühling verwenden (4.2.1.RELEASE; auch ein Upgrade), die diese Methoden auf deploy aufruft, werden alle Debug-Zeiger meisten begrüßen auch ...

bearbeiten 2: (die ganze FactCodeDto Klasse, wie gewünscht)

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

Ihr Ziel, das Sie ist vom Typ bekommen: be.fgov.just.cjr.dto.FactCodeDto was keine Karte ist –

+2

Ja, ich weiß, aber ich will um eine Liste vom Typ FactCodeDto zu bekommen und diese über setResultTransformer (Transformers.aliasToBean (FactCodeDto.class)) in den Hibernate zu bringen, aber dann (aus irgendeinem Grund) versucht Hibernate intern meine FactCodeDto.class (target) in eine Map zu werfen. .. aber es sollte das nicht tun, warum macht es das? – Bamboomy

+0

warum verwenden Sie diese Aufblähung, wenn ein einfaches hql oder Kriterien es lösen würden? – javaguest

Antwort

1

Am Ende es w asn't so schwer, eine Lösung zu finden,

ich nur meine eigene erstellt (custom) ResultTransformer und festgelegt, dass in der setResultTransformer Methode:

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)); 
} 

der Code des Transformators benutzerdefinierten Ergebnis:

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 Hibernate 3 können Sie Aliasse auf Abfragen setzen, aber Sie können nicht mehr in Ruhezustand 5 (korrigieren Sie mich, wenn ich falsch liege) daher die AliasToBean ist etwas, das Sie nur verwenden können, wenn Sie tatsächlich Aliases; was ich nicht tat, daher die Ausnahme.

+0

Es ist möglich, Aliase zu verwenden, siehe meine Antwort http://stackoverflow.com/a/37437567/3405171 –

+0

Und es ist möglich, einen einfacheren und universellen Transformator zu machen, der die Reflexion verwendet. –

4

Ich habe festgestellt, dass AliasToBean in Hibernate 5 geändert hat. Für mich hinzufügen Getter für mein Feld das Problem behoben.

+0

für mich unter ähnlichen Bedingungen musste ich Feldname von sagen sagen 'Postleitzahl' zu 'ZipCode' (alias Kamelfall) ändern und Setter-Methode entsprechend umbenennen. aber trotzdem, Ausnahmetext kann verwirren .. – ashirman

3

Ich mache einige Untersuchungen zu dieser Frage. Das Problem besteht darin, dass Hibernate Aliase für Spaltennamen in Großbuchstaben umwandelt - cdFact wird CDFACT.

liest für eine tiefe Erklärung und Abhilfe hier: mapping Hibernate query results to custom class?

0

Ich war immer diese Ausnahme

ich nannte einen Bereich in DTO als „closedIndexValue“, nachdem es Wechsel zu "closedindexValue ", Der Code funktionierte gut. Ich denke, es war wegen des Buchstabens" I ".

closedIndexValue -> unangebrachter Camelcase closedindexValue -> richtige Camelcase

Hibernate Version: - 5.2.4

0

Diese Ausnahme tritt auf, wenn die Setter und Getter und nicht korrekt zugeordnet zu den Spaltennamen. Stellen Sie sicher, dass Sie die richtigen Getter und Setter für die Abfrage haben (korrekte Namen und korrekte Datentypen). weitere Informationen, lesen Sie hier:

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

+0

Diese Antwort bietet keine Lösung, auch bei korrekter Zuordnung würde die Besetzung nicht funktionieren. – Bamboomy