当前位置: 首页 > 知识库问答 >
问题:

Mybatis当使用自定义泛型typehandler且bean属性名称和表的列相同时,select将引发ClassCastException

逄烨
2023-03-14
<typeHandlers>
        <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType"
            javaType="com.sut.util.meta.WhetherTypeEnum" jdbcType="CHAR"/>
        <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType"
            javaType="com.sut.util.meta.SexTypeEnum" jdbcType="CHAR" />
        <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType"
            javaType="com.sut.util.meta.ArticleTypeEnum" jdbcType="CHAR" />
        <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType"
            javaType="com.sut.util.meta.EducationLevelEnum" jdbcType="CHAR" />
        <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType"
            javaType="com.sut.util.meta.ServiceLevelEnum" jdbcType="CHAR" />
        <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType"
            javaType="com.sut.util.meta.ServiceTypeEnum" jdbcType="CHAR" />
        <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType"
            javaType="com.sut.util.meta.StaffLevelEnum" jdbcType="CHAR" />
        <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType"
            javaType="com.sut.util.meta.ArticleStatusEnum" jdbcType="CHAR" />
        <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType"
            javaType="com.sut.util.meta.HealthyStatusEnum" jdbcType="CHAR" />
</typeHandlers>

staffMapper.xml

 <resultMap type="com.sut.persist.entity.Staff" id="staff">
    <id property="id" javaType="int" column="id" />
    <result property="staffName" javaType="String" column="STAFF_NAME" />
    <result property="imgPath" javaType="String" column="IMG_PATH" />
    <result property="staffLevel" javaType="com.sut.util.meta.StaffLevelEnum" column="LEVEL"
        typeHandler="com.sut.util.enumerate.mybatis.GenericEnumUserType" jdbcType="CHAR"/>
    <result property="birthDate" javaType="java.util.Date" column="BIRTH_DATE" />
    <result property="address" javaType="String" column="address" />
    <result property="healthyStatus" javaType="com.sut.util.meta.HealthyStatusEnum" column="HEALTHY_STATUS"
        typeHandler="com.sut.util.enumerate.mybatis.GenericEnumUserType" jdbcType="CHAR" />
    <result property="education" column="education" typeHandler="com.sut.util.enumerate.mybatis.GenericEnumUserType" /> 
    <result property="workYears" javaType="integer" column="WORK_YEARS" />
    <result property="selfIntroduction" javaType="String" column="SELF_INTRODUCTION" />
    <result property="cert" javaType="String" column="CERT" />
    <result property="remark" javaType="String" column="REMARK" />
    <result property="serviceType" javaType="com.sut.util.meta.ServiceTypeEnum" column="SERVICE_TYPE"
        typeHandler="com.sut.util.enumerate.mybatis.GenericEnumUserType" /> 
    <result property="mobile" javaType="String" column="MOBILE" />
    <result property="qqNumber" javaType="String" column="QQ_NUMBER" />
    <result property="webchatNumber" javaType="String" column="WEBCHAT_NUMBER" />
    <result property="webchatQrcode" javaType="String" column="WEBCHAT_QRCODE" />   
</resultMap>

<!-- query user by id -->
<select id="getById" parameterType="long"  resultMap="staff">
    select
        staff_id,
        staff_name,
        img_path,
        level as staffLevel,
        birth_date,
        address,
        healthy_status as healthyStatus,
        education as education, 
        work_years,
        self_introduction,
        cert,
        remark,
        service_type as serviceType,
        mobile,
        qq_number,
        webchat_number,
        webchat_qrcode
    from bbs_staff where staff_id = #{id}

staff.java:

public class Staff implements java.io.Serializable {

    private static final long serialVersionUID = 1L;

    private long id;
    private String staffName;
    private String imgPath;
    private StaffLevelEnum staffLevel;
    private java.util.Date birthDate;
    private java.lang.String address;
    private HealthyStatusEnum healthyStatus;
    private EducationLevelEnum educationLevel;
    private int workYears;
    private String selfIntroduction;
    private String cert;
    private String remark;
    private ServiceTypeEnum serviceType;
    private String mobile;
    private String qqNumber;
    private String webchatNumber;
    private String webchatQrcode;

    /**
     * default Constructor
     */
    public Staff() {
        super();
    }


    public long getId() {
        return id;
    }


    public void setId(long id) {
        this.id = id;
    }


    public String getStaffName() {
        return staffName;
    }

    public void setStaffName(String staffName) {
        this.staffName = staffName;
    }

    public String getImgPath() {
        return imgPath;
    }

    public void setImgPath(String imgPath) {
        this.imgPath = imgPath;
    }


    public StaffLevelEnum getStaffLevel() {
        return staffLevel;
    }


    public void setStaffLevel(StaffLevelEnum staffLevel) {
        this.staffLevel = staffLevel;
    }


    public java.util.Date getBirthDate() {
        return birthDate;
    }

    public void setBirthDate(java.util.Date birthDate) {
        this.birthDate = birthDate;
    }

    public java.lang.String getAddress() {
        return address;
    }

    public void setAddress(java.lang.String address) {
        this.address = address;
    }

    public HealthyStatusEnum getHealthyStatus() {
        return healthyStatus;
    }

    public void setHealthyStatus(HealthyStatusEnum healthyStatus) {
        this.healthyStatus = healthyStatus;
    }

    public EducationLevelEnum getEducationLevel() {
        return educationLevel;
    }


    public void setEducationLevel(EducationLevelEnum educationLevel) {
        this.educationLevel = educationLevel;
    }

    public int getWorkYears() {
        return workYears;
    }

    public void setWorkYears(int workYears) {
        this.workYears = workYears;
    }


    public String getSelfIntroduction() {
        return selfIntroduction;
    }


    public void setSelfIntroduction(String selfIntroduction) {
        this.selfIntroduction = selfIntroduction;
    }

    public String getCert() {
        return cert;
    }

    public void setCert(String cert) {
        this.cert = cert;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    public ServiceTypeEnum getServiceType() {
        return serviceType;
    }

    public void setServiceType(ServiceTypeEnum serviceType) {
        this.serviceType = serviceType;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getQqNumber() {
        return qqNumber;
    }

    public void setQqNumber(String qqNumber) {
        this.qqNumber = qqNumber;
    }

    public String getWebchatNumber() {
        return webchatNumber;
    }

    public void setWebchatNumber(String webchatNumber) {
        this.webchatNumber = webchatNumber;
    }

    public String getWebchatQrcode() {
        return webchatQrcode;
    }

    public void setWebchatQrcode(String webchatQrcode) {
        this.webchatQrcode = webchatQrcode;
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(Staff.class)
                .add("id", id)
                .add("staffName", staffName)
                .add("imgPath", imgPath)
                .add("level", staffLevel)
                .add("birthDate", birthDate)
                .add("address", address)
                .add("healthyStatus", healthyStatus)
                .add("education", educationLevel)
                .add("workYears", workYears)
                .add("selfIntroduction", selfIntroduction)
                .add("cert", cert)
                .add("remark", remark)
                .add("serviceType", serviceType)
                .add("mobile", mobile)
                .add("qqNumber", qqNumber)
                .add("webChatNumber", webchatNumber)
                .add("webChatQrcode", webchatQrcode)
                .toString();
    }

}

com.sut.util.Enumerate.MyBatis.GenericEnumUserType:

public class GenericEnumUserType<E extends StringEnumTypeImp> extends BaseTypeHandler<E>{

    private static final Logger LOG = LoggerFactory.getLogger(GenericEnumUserType.class);

    //mybatis will pass actual class when constructing TypeHandler
    private Class<E> type;

    private static final String fromStringCode = "fromStringCode";

    public GenericEnumUserType(Class<E> type){
        Preconditions.checkNotNull(type, "Type argument cannot be null");
        this.type = type;
    }

    /**
     * @see org.apache.ibatis.type.BaseTypeHandler#setNonNullParameter(java.sql.PreparedStatement, int, java.lang.Object, org.apache.ibatis.type.JdbcType)
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, StringEnumTypeImp parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, parameter.getStoreValue());
    }

    /**
     * getResult and use reflect 
     * @see org.apache.ibatis.type.BaseTypeHandler#getNullableResult(java.sql.ResultSet, java.lang.String)
     */
    @Override
    @SuppressWarnings("unchecked")
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
        LOG.info("return type is : {}", type);
        String storeValue =  rs.getString(columnName);
        Preconditions.checkNotNull(type, "Type argument cannot be null");
        try {
            Method fromMethod = type.getMethod(fromStringCode, String.class);
            return (E) fromMethod.invoke(null, storeValue);
        } catch (IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 
     * @see org.apache.ibatis.type.BaseTypeHandler#getNullableResult(java.sql.ResultSet, int)
     */
    @SuppressWarnings("unchecked")
    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        LOG.info("return type is {}", type);
        String storeValue =  rs.getString(columnIndex);
        Preconditions.checkNotNull(type, "Type argument cannot be null");
        try {
            Method fromMethod = type.getMethod(fromStringCode, String.class);
            return (E) fromMethod.invoke(null, storeValue);
        } catch (IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * not used
     * @see org.apache.ibatis.type.BaseTypeHandler#getNullableResult(java.sql.CallableStatement, int)
     */
    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        try {
            return type.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

}

当调用getById方法时,它将引发异常:

Struts has detected an unhandled exception:

Messages:   
java.lang.ClassCastException@6f26a5f5
Could not set property 'education' of 'class com.sut.persist.entity.Staff' with value 'com.sut.util.meta.HealthyStatusEnum@3b554a50' Cause: java.lang.IllegalArgumentException: java.lang.ClassCastException@6f26a5f5
nested exception is org.apache.ibatis.reflection.ReflectionException: Could not set property 'education' of 'class com.sut.persist.entity.Staff' with value 'com.sut.util.meta.HealthyStatusEnum@3b554a50' Cause: java.lang.IllegalArgumentException: java.lang.ClassCastException@6f26a5f5 

共有1个答案

贲永思
2023-03-14
<result property="educationLevel" column="education" javaType="com.sut.util.meta.EducationLevelEnum" jdbcType="CHAR" />
    null
 类似资料:
  • 在Spring IOC中,bean的两个定义(具有相同的名称和类)是否有效? 我有两个bean定义文件包含在web中。xml。参见下面的示例。 应用Context-beans1.xml applicationContext-beans2。xml 到目前为止,我还没有遇到任何问题。但是,这可能会影响到多线程和集群的现实环境吗? 注意:这两个XMLs都被加载,因为我可以使用在这两个XMLs中定义的其他

  • 问题内容: 我正在使用JavaScriptSerializer反序列化json数据。一切工作都很好,但是我的问题是,json数据中的一个属性被命名为“ base”,所以我无法在C#代码中创建这样的属性。我发现我可以手动将值映射到构造函数中的属性,但是问题是,我的DTO具有200个属性,因此我不想手动进行此操作,而是希望找到任何其他解决方案。我也尝试使用注释,但这是: 并没有帮助我,每次将baseV

  • 问题内容: H2似乎在带引号的名称和不带引号的名称之间有所不同。有没有办法让他们以相同的方式对待他们? 这是我已经完成的测试: 这是查询: 我该怎么做才能使这些查询与H2一起使用? 问题答案: 根据SQL规范的要求,H2中的引号名称区分大小写。这意味着它将起作用: 但这不会: 在H2中,不带引号的名称不区分大小写。它们通常会转换为大写字母(例如在Oracle和其他数据库中)。这意味着声明 与…相同

  • 我有一个棘手的XML要散集: 我的第一个想法是: 但是因为根元素和列表元素都命名为“供应商”,所以它给了我一个例外: 当我删除供应商类别上的@XmlRootElement(名称=“供应商”)时,它开始正确取消封印。 有人能解释一下处理这个棘手的XML的正确方法是什么吗?为什么我的解决方法有效?

  • 问题是我的控制器中有一个spring表单和两个具有相同属性的@ModelAttribute参数。表单的“commandName”参数设置为我的modelAttributes名称之一。令我惊讶的是,不仅将属性映射到用“commandName”指定的模型属性,还映射到第二个属性。 我还没有找到确切的解决方案,除了和我的相似之处:Spring-form多个表单具有相同的模型属性名称属性 但在我的例子中,

  • 当我打开localhost:8080/customers/searchCustomer时,会引发异常: org.springframework.beans.NotReadable属性异常:bean类[java.lang.字符串]的无效属性ssn:Bean属性ssn不可读或具有无效的getter方法:getter的返回类型是否与setter的参数类型匹配? 我的接球手和二传手都很好。 我的实体: 在