2017-01-07 5 views
0

Mybatis를 처음 사용합니다. 최근에 나는 커스텀 generic 타입을 사용했다 .Hander, bean 속성이 테이블의 컬럼 이름과 같을 때, select는 ClassCastException을 발생시킬 것이다. 다음Mybatis가 사용자 정의 제네릭 typehandler를 사용할 때 bean 속성 이름과 테이블의 열이 동일하면 select가 ClassCastException을 발생시킵니다.

구성을

의 MyBatis-의 configuration.xml

<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 있습니다

,210

com.sut.util.enumerate.mybatis.GenericEnumUserType : 일반 TypeHandler 사용시

Struts has detected an unhandled exception: 

Messages: 
[email protected] 
Could not set property 'education' of 'class com.sut.persist.entity.Staff' with value '[email protected]' Cause: java.lang.IllegalArgumentException: [email protected] 
nested exception is org.apache.ibatis.reflection.ReflectionException: Could not set property 'education' of 'class com.sut.persist.entity.Staff' with value '[email protected]' Cause: java.lang.IllegalArgumentException: [email protected] 

의 MyBatis 문서 상기 다음 getById 메소드를 호출 할 때, 예외를 발생한다

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

} 

JavaType에 의해 jdbcType가 null 일지라도, 올바른 TypeHandler를 얻습니다. 구성을 세 번 확인하고 소스 코드를 디버깅했습니다. 그런 다음 ResultSetWrapper가 mappedColumns 및 UnmappedColumns에 열을 분리한다는 것을 알아 냈습니다. mappedColumns는 그렇지 않으므로 unmappedColumns가 올바른 TypeHandler를 반환합니다. 나는 이것이 왜 일어나는 지 궁금하다. 이 버그 또는 내 구성이 올바르지 않습니다.

환경 :
의 MyBatis : 3.4.1
MySQL은 : 5.6

어떤 도움을 이해할 수있을 것이다! 실제 mapper.xml에서

+0

안녕하세요, (MyBatis로 그것을 할 수 있습니다) w. com.sut.util.enumerate.mybatis.GenericEnumUserType의 구현도 제공해 주시겠습니까? – hakamairi

+0

답장을 보내 주셔서 감사합니다. 'GenericEnumUserType' 코드를 추가했습니다 .. –

+0

Staff 클래스도 추가 할 수 있습니까? – hakamairi

답변

0

당신은 처리 유형

당신 POJO educationLevel에에서 대신 교육의 속성 이름에
<result property="educationLevel" column="education" javaType="com.sut.util.meta.EducationLevelEnum" jdbcType="CHAR" /> 
  • 경기
  • 이 만약 javaType과 jdbcType을 제공 열거에 대한 다음과 같은 작업을 수행 할 시도 할 수 있습니다
  • 결과 매핑에서 핸들러를 제거 Stackoverflo에 오신 것을 환영합니다
+0

이것은 성공했습니다! 하지만 이유를 알아낼 수 없다 –

+0

특정 java 및 jdbc 유형 쌍에 대해 myBatis를 사용하여 핸들러를 등록했습니다. 이제는 myBatis가 핸들러를 검색하는 유형을 기반으로 합니다만, jdbc 유형을 건너 뛰어도 실제 POJO에서 Java 유형을 검색하지만 자체적으로 처리해야합니다. 이것은 실제 핸들러 생성 - 생성자에서 적절한 Enum 유형을 제공해야하는 경우에 중요합니다. – hakamairi

+0

맞습니다. 아마도 resultMapping에서 사용자 정의 유형 핸들러를 사용하는 올바른 방법 일 것입니다. 당신의 도움을 주셔서 감사합니다 –