当前位置: 首页 > 面试题库 >

Hibernate给出了一个奇怪的ClassCast异常(使用Transformers)

马和硕
2023-03-14
问题内容

这段代码:

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

调用此方法:

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

给我一个ClassCastException->跟踪的一部分:

Caused by: java.lang.ClassCastException: org.bamboomy.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 org.bamboomy.cjr.dao.factcode.FactCodeDAOImpl.getAllFactsWithoutParentsAsFactDto(FactCodeDAOImpl.java:133)

这很奇怪,因为,实际上,如果您查找Hibernate的源代码,它将尝试执行以下操作:

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

这没有任何意义…

目标的类型为Class,此代码尝试将其强制转换为Map,

为什么要尝试这样做???

任何指针都值得欢迎…

我正在使用Hibernate 5(并且正在从3升级)…

编辑:我也使用Spring(4.2.1.RELEASE;也进行升级),它在部署时调用这些方法,任何调试指针也都非常受欢迎…

编辑2 :(根据要求,整个FactCodeDto类)

package org.bamboomy.cjr.dto;

import org.bamboomy.cjr.model.FactCode;
import org.bamboomy.cjr.model.FactCodeType;
import org.bamboomy.cjr.utility.FullDateUtil;
import org.bamboomy.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();
    }


}

问题答案:

最后,找到解决方案并不难,

我刚刚创建了自己的(自定义)ResultTransformer,并在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));
}

自定义结果转换器的代码:

package org.bamboomy.cjr.dao.factcode;

import org.bamboomy.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;
    }
}

在hibernate3中,您可以将Aliasses设置为查询,但是在hibernate5中不能再执行此操作(如果我错了,请纠正我),因此aliasToBean是您只能在实际使用别名时使用的东西;我没有,所以例外。



 类似资料:
  • 问题内容: 我正在尝试在节点中使用Express,安装一切正常,进行编译,获取npm并通过以下方式安装express: npm安装快递 问题是,每次我尝试“要求”它时,都会给我一个错误!看一下一个简单的文件app.js: 当我运行它时: 有人能帮我吗?为什么会出现此错误?如何安装与Express不同的版本? 问题答案: 问题是,你可能有最新的连接(而不是“您需要安装最新的连接”)的命令@Shrip

  • 问题内容: 基本上,该网站可以正常运行12多个小时,然后突然停止工作。我将开始在以前运行良好的LINQ查询中引发奇怪的异常。 我在这篇文章的底部提供了堆栈跟踪。 根据在类似SO帖子上找到的建议,我通过直接从Server Explorer中的DB拖动表来删除并重新制作了DBML。比较Git中的新旧内容,我发现了一些不同的字段: 在dbml中将varchar(255)的一个实例设置为nchar(10)

  • 我想用fsolve数值求解一个非线性超越方程的根。 下面的代码执行此任务。

  • 在运行我的项目时,我在android studio中收到ClassCastException。谁能告诉我是什么导致了这个错误。 com.intellij.psi.impl.source.PsiPlainTextFileImpl不能转换为com.intellij.psi.xml.XmlFile 谢谢。

  • 我在Digitalocean上安装了一个VPS服务器。安装了Ubuntu 18.04、LAMP等。最后,我安装了ffmpeg。它在终端上运行良好,但当我尝试通过php执行它时,会出现一个奇怪的“权限被拒绝”错误: 以下是一些信息: root@vl:/#何去何从ffmpeg ffmpeg: /usr/local/bin/ffmpeg root@vl:/#何去何从ff探针: /usr/local/bi

  • 问题内容: 我在做什么 : 我预期的输出: 平均=(10 + 20 + 30)/ 5 = 12 MYSQL的输出: 平均值=(10 + 20 + 30)/ 3 = 20 理想情况下,我想要的是MYSQL应该得到5行的总和并除以5,但是它只能除以3(非NULL行) 为什么会发生这种情况,我该怎么做才能获得正确的AVG,即60/5?PS:我不能使标记字段NOT NULL,在我的数据库设计中,标记字段允